题目:UVA 1635
题目大意:
对于给定的n个数a1,a2,a3....an,一次求出相邻两个数之和,将得到一个新的数列。重复上述操作,最后结果将变成一个数。问这个数除以m的余数与那些数无关?例如n=3,m=2时,第一次求和结果a1+a2,a2+a3,在求和a1+2a2+a3,它除以2的余数和a2无关,1<=n<=10^5,2<=m<=10^9
分析:
C(k,n)=(n-k+1)/k*C(k-1,n),如果直接去求C(i-1,n-1)会爆long long 。那么就用唯一分解定理先将m分解了,然后在对C(i-1,n-1)分解了,看他们的素因子的指数是否合理,如果合理就是倍数关系。所谓合理就是C(i-1,n-1)的每一个素因子指数都要大于等于m的素因子指数
代码:
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> #include<math.h> using namespace std; const int max_=1e5+5; int pow_prime[max_][2]; int fen[max_]; int num[max_]; int tot; void putm(int n) { tot=0; for(int i=2;i*i<=n;i++) { if(n%i==0) { int s=0; while(n%i==0) { s++; n/=i; } pow_prime[tot][0]=s; pow_prime[tot++][1]=i; } } if(n>1) { pow_prime[tot][0]=1; pow_prime[tot++][1]=n; } } bool check(int n,int k) { int x=n-k+1; int y=k; for(int i=0;i<tot;i++) { int p=pow_prime[i][1]; int& q=fen[i]; while(x%p==0)//fen数组会累加,相当于递推 { q++; x/=p; } while(y%p==0) { q--; y/=p; } } for(int i=0;i<tot;i++) { if(fen[i]<pow_prime[i][0]) return 0; } return 1; } int main() { int n, m; while(~scanf("%d %d",&n,&m)) { putm(m); int sum=0; memset(fen,0,sizeof(fen)); for(int i=1;i<n;i++) { if(check(n-1,i)) { num[sum++]=i+1; } } printf("%d\n",sum); for(int i=0;i<sum;i++) { if(i==0) printf("%d",num[i]); else printf(" %d",num[i]); } printf("\n"); } }