题意:给定一个序列,依次求出相邻两个数字的和,将得到一个新序列,重复上述过程直到最后的结果是是一个数。求最后的数除m的余数和原序列中的那些数无关。
题解:模拟可以得出最后一个数是原序列的线性和。没一项的系数恰好满足杨辉三角的规律。C(k,n)=(n-k+1)/k*C(k-1,m)。用这个可以0(n)的复杂度推出系数。但是由于数据很大,如果直接推的话,要用大数处理,过于麻烦。考虑到这里只关心那些系数是m的倍数,对于很大的数我们可以用唯一分解定理,把他以素数因子指数的形式处理,而且指数的关系是可以通过C(k,n)=(n-k+1)/k*C(k-1,m)这个关系式递推的。
ac代码:
#include <cstdio> #include <iostream> #include <cstring> #include <queue> using namespace std; int n,m; int prime[10001]; int e[10001]; int c[100001]; int init()// 唯一分解定理 { int ret=0; for(int i=2;i*i<=m;i++) { if(m%i==0) { prime[ret]=i; while(m%i==0) { e[ret]++; m/=i; } ret++; } } if(m>1) { prime[ret]=m; e[ret++]++; } return ret; } int e2[100001]; int check(int len) { for(int i=0;i<len;i++) { if(e2[i]<e[i]) return 0; } return 1; } int main() { while(cin>>n>>m) { // cout<<sum<<endl; memset(e,0,sizeof(e)); int ret=0; queue<int> out; memset(c,0,sizeof(c)); memset(e2,0,sizeof(e2)); int sum=init();// c[0]=1; for(int i=1;i<n;i++) { int temp=n-1-i+1;// 对应n为多少要理清楚 int zz=i; // cout<<temp<<' '<<zz<<endl; for(int j=0;j<sum;j++)// 递推指数关系的时候,由于有除法,可能出限小数,所以我们分子,分母分开处理 { if(temp%prime[j]==0) { while(temp%prime[j]==0) { e2[j]++; temp=temp/prime[j]; // cout<<1<<endl; } } if(zz%prime[j]==0) { while(zz%prime[j]==0) { e2[j]--; zz=zz/prime[j]; // cout<<2<<endl; } } } if(check(sum)) { ret++; out.push(i+1); } } cout<<ret<<endl; if(ret!=0) { cout<<out.front(); out.pop(); } while(!out.empty()) { cout<<' '<<out.front(); out.pop(); } cout<<endl; } return 0; }