算法竞赛入门经典第十章知识点总结

欧几里得算法

算法引入:除法表达式

题目描述

给出一个这样的除法表达式: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的合数都被前面的素数筛了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Greatljc

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值