[数论]Irrelevant Elements, ACM/ICPC NEERC 2004, Uva1635
2017-12-27 21:51
399 查看
[唯一分解定理在组合数学中的简单应用]
题意:给定n个数a1,a2…an,依次求出相邻两个数之和,将得到一个新数列。重复这个操作,最终将得到一个数。问这个数除以m的余数与原数列中的哪个数无关。
题解:最后的求和显然是a1,a2…an的一个线性组合。设ai的系数为f(i),那么当且仅当f(i)是m的倍数时,最终结果除以m的余数与ai无关。
此时这个问题变成:找出最终的线性组合中哪些项的系数是m的倍数。
题目中给出的操作是不断将相邻的两个数相加,每一层的数都可以表示为上一层两个相邻数的和,显然这是一个杨辉三角,而它的性质就是第n行的第i个数为C(n-1,i-1)。
此时这个问题变成:对于给定的一个整数n,找出C(n-1,0)到C(n-1,n-1)这n个数中有哪些数是m的倍数。
理论上可以利用C(n,k)=C(n,k-1)*(n-k+1)/k递推出所有的组合数,但n的范围1e5,只能使用高精度。这时需要注意到,本题只是要判断哪些是m的倍数,并不要求求出所有的组合数。这里利用数论中的唯一分解定理,依次计算m的唯一分解式中各个素因子在C(n-1,i-1)中的指数即可完成判断,而对组合数进行判断时仍然可以使用上述公式进行递推。
还需注意的是,本题判断m的倍数不能采取递推取模的方法。原因是递推式中含有除法,而模m意义下的逆元只有在与m互质时才存在。
题意:给定n个数a1,a2…an,依次求出相邻两个数之和,将得到一个新数列。重复这个操作,最终将得到一个数。问这个数除以m的余数与原数列中的哪个数无关。
题解:最后的求和显然是a1,a2…an的一个线性组合。设ai的系数为f(i),那么当且仅当f(i)是m的倍数时,最终结果除以m的余数与ai无关。
此时这个问题变成:找出最终的线性组合中哪些项的系数是m的倍数。
题目中给出的操作是不断将相邻的两个数相加,每一层的数都可以表示为上一层两个相邻数的和,显然这是一个杨辉三角,而它的性质就是第n行的第i个数为C(n-1,i-1)。
此时这个问题变成:对于给定的一个整数n,找出C(n-1,0)到C(n-1,n-1)这n个数中有哪些数是m的倍数。
理论上可以利用C(n,k)=C(n,k-1)*(n-k+1)/k递推出所有的组合数,但n的范围1e5,只能使用高精度。这时需要注意到,本题只是要判断哪些是m的倍数,并不要求求出所有的组合数。这里利用数论中的唯一分解定理,依次计算m的唯一分解式中各个素因子在C(n-1,i-1)中的指数即可完成判断,而对组合数进行判断时仍然可以使用上述公式进行递推。
还需注意的是,本题判断m的倍数不能采取递推取模的方法。原因是递推式中含有除法,而模m意义下的逆元只有在与m互质时才存在。
//80ms #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<queue> #include<vector> #include<iostream> #include<algorithm> #define maxp 32001 #define maxn 100050 #define INF 0x3f3f3f3f #define eps 1e-8 using namespace std; typedef long long ll; int n, m, im, ans, en; int prime[maxp], pnum = 0, pm[20], em[20]; bool flag[maxp], vis[maxn]; void getpri() { memset(flag, 0, sizeof(flag)); int p = sqrt(maxp + 0.5); for (int i = 2; i <= p; i++) { for (int j = i*i; j < maxp; j += i) flag[j] = 1; } for (int i = 2; i < maxp; i++) { if (!flag[i]) prime[pnum++] = i; } } void init() { memset(pm, 0, sizeof(pm)); memset(em, 0, sizeof(em)); im = 0; for (int i = 0; i < pnum&&prime[i] <= m; i++) { if (m%prime[i] == 0) { pm[im] = prime[i]; while ((m%prime[i] == 0) && (m /= prime[i])) em[im]++; im++; } if (n == 0 || n == 1) break; } if (m > 1) { pm[im] = m; em[im++] = 1; } } bool getfac(int x, int y) { bool cnt = true; for (int i = 0; i < im; i++) { while (x%pm[i] == 0 && (x /= pm[i])) em[i]--; while (y%pm[i] == 0 && (y /= pm[i])) em[i]++; if (em[i] > 0) cnt = false; } return cnt; } int main() { getpri(); while (scanf("%d%d", &n, &m) != EOF) { init(); ans = en = 0; memset(vis, 0, sizeof(vis)); for (int i = 1; i <= n; ++i) { if (getfac(n - i, i)) { vis[i + 1] = true; ans++; en = i + 1; } } printf("%d\n", ans); if (ans) { for (int i = 1; i < en; i++) { if (vis[i]) printf("%d ", i); } printf("%d", en); } printf("\n"); } return 0; }
相关文章推荐
- 【数论】Irrelevant Elements, ACM/ICPC NEERC 2004, UVa1635 【组合数学】
- UVA 1587 Box 【ACM/ICPC NEERC 2004】
- 例题7-14 网格动物(Lattice Animals, ACM/ICPC NEERC 2004, UVa1602)
- 环装序列 (Circular Sequence, ACM/ICPC Seoul 2004, UVa1584)
- UVA 1635 Irrelevant Elements [唯一分解定理]
- Cable TV Network, ACM/ICPC SEERC 2004, UVa1660【Dinic 最小割 拆点】
- Irrelevant Elements UVA - 1635(组合数,唯一分解定理)
- UVA 1635-Irrelevant Elements(唯一分解定理)
- UVa 1635 - Irrelevant Elements(唯一分解)
- UVA1635 Irrelevant Elements(唯一分解定理 + 组合数递推)
- UVA1635 Irrelevant Elements —— 唯一分解定理 + 二项式定理
- Irrelevant Elements UVA - 1635 唯一分解定理
- UVA 1635 Irrelevant Elements
- 环状序列(Circular Sequence, ACM/ICPC Seoul 2004, UVa1584)
- Irrelevant Elements UVA - 1635 唯一分解定理
- UVA 1588 Kickdown & ACM/ICPC NEERC 2006 解题报告
- UVA 1336 Fixing the Great Wall - ACM/ICPC CERC 2004
- Irrelevant Elements UVA - 1635 唯一分解定理
- uva-1635-Irrelevant Elements-唯一分解定理,组合数
- UVA 1635 Irrelevant Elements