目录
一 基础数论知识
1.1 求最大公约数(欧几里得算法)
int gcd(int x, int y)
{
return !y ? x : gcd(y, x % y); //辗转相除法
}
1.2 求最小公倍数
两数的最小公倍数等于两数成积除以两数最大公约数。
return x*y/gcd(x,y);
1.3 根相减损术
gcd(a,b)=gcd(b-a,a)
如:gcd(4,6)=gcd(2,4)
1.4 唯一分解定理
Ⅰ
唯一分解定理:对于一个大于1的整数n,n可以分解质因数为:
其中表示
的第
个质因子,
表示
的幂次,如
(此时
,
,
,
)
//对n进行质因数分解
void divide(int n) {
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) {
int j = 0;
while (n % i == 0) {
n /= i;
j++;
}
cout << i << ' ' << j << endl; //i是质因数,j是幂次
}
}
if (n > 1) cout << n << ' ' << 1;
}
Ⅱ
的质因子
的个数公式:
例如求n阶乘中5因子的个数的公式就是:n/5+n/25+n/125+n/5^i
int query(int n) {
int ret = 0;
while (n > 0) {
ret += n / 5;
n /= 5;
}
return ret;
}
1.5 约数定理
一个正整数n的正约数的个数
其中表示正整数
的质因子的幂次(见唯一分解定理)
二 例题
2.1 GCD
问题描述
给定两个不同的正整数a,b,求一个正整数k使得gcd(a + k,b+k)尽可能大,其中gcd(a,b)表示α和b的最大公约数,如果存在多个k,请输出所有满足条件的k中最小的那个。
输入格式
输入一行包含两个正整数a,b,用一个空格分隔。
输出格式
输出一行包含一个正整数k。
题目分析
因为gcd(a,b)=gcd(b-a,a) [b < a](更相减损术),所以gcd(a+k,b+k)=gcd(a+k,b-a)≤min(a+k,b-a),要最大化gcd(a+k,b-a),直接令gcd=b-a,故a+k=n(b-a) [n为正整数]
引论:若a+k = n*c ,则 k=c-(a%c);
故k=(b-a)-(a%(b-a));
#include <iostream>
typedef long long int LL;
using namespace std;
LL a, b, c,d;
int main()
{
// 请在此输入您的代码
cin>>a;
cin>>b;
c=b-a;
d=c-(a%c);
cout<<d;
return 0;
}
2.2 求阶乘
问题描述
满足N!的末尾恰好有K个0的最小的N是多少?
如果这样的N不存在输出―1。
输入格式
—个整数 K。
输出格式
—个整数代表答案。
题目分析
根据唯一分解定理可知,N!可以分解为若干质因数的乘积(如2、3、5、7)。故可知N!的末尾0的个数取决于质因数2的个数和质因数5的个数(只有2与5相乘才会产生0)。而的质因子
的个数公式:
,故可知质因数5的个数一定小于质因数2的个数,所以N!的末尾0的个数取决于质因数5的个数。
这里使用二分法来求取最小的N
//结尾为0就是分解质因数5的个数,有多少5的倍数其阶乘末尾就有多少个0
//求n阶乘中5因子的个数的公式就是n/5+n/25+n/125+⋅⋅⋅+n/5^i
#include <iostream>
#define ll long long
using namespace std;
ll query(ll n) {
ll ret = 0;
while (n > 0) {
ret += n / 5;
n /= 5;
}
return ret;
}
int main() {
ll k;
cin >> k;
ll l = 1, r = 0x7fffffffffffffffL; // long long的最大
while (l < r) {
ll mid = l + (r - l >> 1);
if (query(mid) < k) l = mid + 1;
else r = mid;
}
ll ret = query(l);
if (ret == k) cout << l;
else cout << -1;
return 0;
}
2.3 阶乘约数
题目描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
定义阶乘n! = 1 x2 ×3×···×n。
请问100! (100的阶乘)有多少个正约数。
题目分析


#include<bits/stdc++.h>
using namespace std;
const int N = 1e2 + 10;
int cnt[N]; // cnt[i] 存的是质因子 i 的幂次
signed main()
{
for(int i = 1 ; i <= 100 ; i ++)
{
int x = i;
// 质因子分解
for(int j = 2 ; j * j <= x ; j ++)
{
if(x % j == 0)
{
while(x % j == 0) x /= j , cnt[j] ++ ; // j是其中一个质因子
}
}
if(x > 1) cnt[x] ++ ;
}
long long ans = 1;
for(int i = 1 ; i <= 100 ; i ++)
{
if(cnt[i] != 0) ans *= (cnt[i] + 1);
}
cout << ans << '\n';
return 0;
}
文章介绍了数论的一些基础知识,包括欧几里得算法求最大公约数、最小公倍数的计算、根相减损术、唯一分解定理以及约数定理。此外,还通过例题展示了如何求解阶乘和利用唯一分解定理计算特定质因数的个数,并应用二分法解决与最大公约数相关的数学问题。
327

被折叠的 条评论
为什么被折叠?



