题意:给定n个数a1,a2····an,依次求出相邻两个数值和,将得到一个新数列,重复上述操作,最后结果将变为一个数,问这个数除以m的余数与那些数无关?
思路:最后观察期规律符合杨辉三角,那么,问题就可以变成判断C(0,n-1),C(1,n-1)。。。。C(n-1,n-1)哪些是m的倍数,所以只需考虑m唯一分解后在C(i,n-1)中的情况
公式:C(k,n)=(n-i+1)*c(i-1,n)/k. 然后利用递推公式检查m的因子,只要(n-i+1)/i是m倍数即可
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <map> #include <vector> using namespace std; typedef long long ll; typedef unsigned long long ull; int pm[1000],nm[1000]; int cur; void ini(int m) //分解m { cur = 0; memset(pm,0,sizeof(pm)); memset(nm,0,sizeof(nm)); for(int i = 2; i*i <= m ; i ++) { if(m % i == 0) { pm[cur] = i; while(m % i == 0) { m /= i; nm[cur]++; } cur++; } } if(m > 1) { pm[cur] = m; nm[cur++] = 1; } } bool can_do(int x,int y) //检查因子 { bool flag=true; for(int i=0; i<cur; ++i) { while((x%pm[i]==0) && (x/=pm[i])) nm[i]--; while((y%pm[i]==0) && (y/=pm[i])) nm[i]++; if(nm[i]>0) flag=false; } return flag; } int ans[100050]; int main() { int m,n; while(~scanf("%d%d",&n,&m)) { ini(m); int tot = 0; for(int i = 1; i <= n; i++) { if(can_do(n-i,i)) //n-i = (n-1)-i+1 { ans[tot++] = i+1; } } printf("%d ",tot); if(tot != 0) { for(int i = 0; i < tot-1; i++) if(ans[i]) printf("%d ",ans[i]); printf("%d",ans[tot-1]); } printf(" "); } return 0; }