Uva1635 二项式递推+质因子分解+整数因子分解
题意:
给定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
解法:
将所有的加法过程列出来可以得到,n个数合并成1个数需要n-1步,且最后的表达式写成初始项相加的形式 每一项的系数恰好就是一个二项式系数。
问除以m的余数与那些数无关,其实就是问这些因子中哪些是m的倍数。我们还是用分解m质因子的方法,将m的质因子全部先分解出来,然后遍历每个二项式系数,看他们能否整除这些质因子(如果这个二项式系数改写成质因子的幂次形式,的这个幂小于m中的这个幂,就不行) 。
除此之外还要学习的就是怎么计算这个幂次,尤其是被除数为分数的时候,分子的幂次的贡献为正,分母为负
1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 using namespace std; 5 int vis[100000 + 5]; 6 7 int work_quality_factor(int n, int quality_fac[], int frequency[]) 8 {//n是待分解的数,quality_fac[]会存放它包含的质因子,而frequency[]存放对应次数 9 //如q_f[k]=7,fre[k]=2就表示质因数分解后里面包含有7,且次数是2 10 //函数返回有几种质因子,比如分解了25就返回1,分解28返回2 11 int res, temp, i; 12 res = 0; 13 temp = n; 14 for (i = 2; i*i <= temp; i++) 15 if (temp%i == 0) 16 { 17 quality_fac[res] = i; 18 frequency[res] = 0; 19 while (temp%i == 0) 20 { 21 temp = temp / i; 22 frequency[res]++; 23 } 24 res++; 25 } 26 if (temp > 1) 27 { 28 quality_fac[res] = temp; 29 frequency[res++] = 1; 30 } 31 return res; 32 } 33 34 int main() { 35 int n, m; 36 while (scanf("%d%d", &n, &m) != EOF) { 37 n--; 38 memset(vis, 0, sizeof(vis)); 39 int fac[100], frq[100]; 40 int primenum = work_quality_factor(m, fac, frq); 41 42 for (int i = 0; i < primenum; i++) { 43 int min_e = frq[i], x, e = 0; 44 // c(n,k)=c(n,k-1)*(n-k+1)/k 45 for (int k = 1; k < n; k++) { 46 //分成上下两部分除,上面的幂次的贡献为正,下面为负 47 x = n - k + 1; 48 while (x%fac[i]==0) { x /= fac[i]; e++; } 49 x = k; 50 while (x%fac[i]==0) { x /= fac[i]; e--; } 51 if (e < min_e)vis[k] = 1; 52 } 53 } 54 55 vector<int>ans; 56 for (int i = 1; i < n; i++) 57 if (!vis[i])ans.push_back(i + 1); 58 printf("%d\n", ans.size()); 59 if (!ans.empty()) { 60 printf("%d", ans[0]); 61 for (int i = 1; i < ans.size(); i++) 62 printf(" %d", ans[i]); 63 } 64 printf("\n"); 65 } 66 return 0; 67 }