欧几里得算法
算法引入:除法表达式
题目描述
给出一个这样的除法表达式:X1/X2/X3/·····/Xk,其中Xi是正整数。除法表达式应当按照从左到右的顺序求和。但是可以在表达式中嵌入括号以改变计算方式。
输入X1/X2/X3/·····/Xk,判断是否可以通过添加括号,使得表达式的值为整数。K <= 10000, Xi <= 109
不难发现,无论括号怎么摆,怎么加,X1必然在分子,X2必然在分母。
关键是其他X3…Xk
书本直接给出了
E = X1/(X2/X3/····Xk) = (X1/X3/·····/Xk) / X2
再去判断E是否为整数。
书本并没有解释为什么这样做可以。
换句话说,如果将除了X2其他的Xi都写在分子,如果得到的E不为整数,那么无论怎么添加括号都不会是整数。或许会有疑问,那我把X3,X4,Xi,放分母试试不行吗?事实上不行。
粗略证明
反证法
E * X2 = X1X3·····Xk E 不为整数
现在把Xi(i != 1)放在分母
此时式子等于
A’= X1···Xi-1Xi+1···Xk 1
B’ = X2Xi 2
此时
E’ * X2Xi = X1···Xi-1Xi+1···Xk
E * X2 = X1X3·····Xk
第二条式子两边乘上Xi,得:
E = E’ * Xi2
如果E不为整数,E’不可能为整数。因为Xi2必定也为正整数。
所以矛盾。所以当E不为整数时,表达式X1/X2/X3/·····/Xk不可能得到整数结果。
同理可证B’ = X2 * Xi ··· * Xk
欧几里得算法(辗转相除法)代码表示
/*
*gcd(a,b) = gcd(b, a % b)
*边界情况gcd(a, 0) = a
*/
int gcd(int a, int b) {
return b == 0 ? a, gcd(b, a % b);
}
除法表达式代码
int judge(int *X) {
X[2] /= gcd(X[1, X[2]);
for(int i = 3; i <= k; ++i) {
X[2] /= gcd(X[i], X[2]);
}
return X[2] == 1;
}
Eratosthenes筛法
算法引入
无平方因子的数
题目描述:给出正整数n和m,区间[n,m]内的“无平方因子”的数有多少个?
整数p无平方因子当且仅当不存在 k>1,使得p是k2的倍数。
我看到书本下面一大篇幅来介绍素数筛法。是不是和素数有关系。
重新看一下问题。
整数p无因子当且仅当不存在 k > 1,使得p时k的倍数。
没错,就和判断p是不是素数很相似。
代码解释
int m = sqrt(n + 0.5); //求根号的意思
int v[maxn];
memset(v, 0, sizeof(v));
for(int i = 2; i <= m; ++i) {
if(!v[i]) {
for(int j = i * i; j <= n; j += i) {
v[j] = 1;
}
关于代码有两点要解释的
- 为什么进入内部循环要判定是不是素数?
- 因为小于目前素数的合数必然被更小的素数筛了。只有素数才是漏网之鱼。
- 内部循环为什么从i * i开始
- 因为小于i * i的合数都被前面的素数筛了。