原题链接:点击打开链接
题意:给定n个数a1,a2····an,依次求出相邻两个数值和,将得到一个新数列,重复上述操作,最后结果将变为一个数,问这个数除以m的余数与那些数无关?例如n=3,m=2时,第一次得到a1+a2,a2+a3,在求和得到a1+2*a2+a3,它除以2的余数和a2无关。1=<n<=10^5, 2=<m<=10^9
思路:
1、首先我们可以发现对于给定的n其实每项的系数就是C(n-1,i-1),所以我们只需要找到每项的系数对m取余是否为0即可
2、由于m的取值范围为10^9,所以我们只需要筛选 √(10^9)的素数,然后对m进行分解;如果分解后m>1,说明当前m的是一个素数,而且m> √(10^9),因此我们只需记录它即可
3、根据C(n,k)=C(n,k)*(n-i+1)/i;(根据这个公式我们可以发现C(n,k)*(n-i+1)一定能整除i),对m分解式中的素数进行操作即可,具体见代码
这题虽然不难,但我WA了好几次,花了好久才发现是取消同步的问题,这是个坑,看来不能随便用取消同步o(╯□╰)o/*************************************************************************
> File Name: 1635.cpp
> Author: Clannad
> Mail: 821199012@qq.com
> Created Time: Mon 11 July 2016 09:03:28 PM
************************************************************************/
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include<string>
#include <ctime>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=32000;//32000*32000=1024e6;
int prime[maxn+1];
int nprime;
void getprime(){
int m=sqrt(maxn+0.5);
for(int i=2 ; i<m ; i++)if(!prime[i])
for(int j=i*i ; j<=maxn ; j+=i)prime[j]=1;
nprime=0;
for(int i=2 ; i<=maxn ; i++){
if(!prime[i])
prime[nprime++]=i;
}
}
int n,m;
int pm[20];
int km[20];
int cnt;
void init(){
memset(pm,0,sizeof(pm));
memset(km,0,sizeof(km));
cnt=0;
for(int i=0 ; i<nprime&&m>=prime[i] ; i++){
if(m%prime[i]==0) {
pm[cnt]=prime[i];
while((m%prime[i]==0)&&(m/=prime[i]))
km[cnt]++;
cnt++;
}
if(n==0||n==1)break;
}
if(m>1){
pm[cnt]=m;
km[cnt]=1;
cnt++;
}
}
bool getfactors(int x,int y){
bool f=true;
for(int i=0 ; i<cnt ; i++){
while((x%pm[i]==0)&&(x/=pm[i]))
km[i]--;
while(y%pm[i]==0&&(y/=pm[i]))
km[i]++;
if(km[i]>0)f=false;
}
return f;
}
bool flag[100010];
int main(){
// std::ios::sync_with_stdio(false);
// #ifndef ONLINE_JUDGE
// freopen("inF.txt", "r", stdin);
// #endif
getprime();
while(cin>>n>>m){
init();
memset(flag,false,sizeof(flag));
int ans=0,ends=0;
for(int i=1 ; i<=n ; i++){
if(getfactors(n-i,i)){
flag[i+1]=true;
ans++;
ends=i+1;
}
}
printf("%d\n",ans);
if(ans!=0){
for(int i=1; i<ends; i++)
if(flag[i])
printf("%d ",i);
printf("%d",ends);
}
printf("\n");
}
return 0;
}
探讨给定数列通过连续求和直至只剩单一数值过程中,最终值除以特定数m的余数与哪些初始数无关。通过组合数学原理确定各数在最终结果中的系数,并利用素数分解及模运算特性解决此问题。
&spm=1001.2101.3001.5002&articleId=51883937&d=1&t=3&u=2c97f9cd5d8545cead8b7ea0d8a233b5)
560

被折叠的 条评论
为什么被折叠?



