数论
前言:这是一篇个人学习过程的记录,文章供正在学习大家一起分享,如有不完整,不正确的地方,欢迎留言补充指正。
欧几里得算法(裴蜀定理 - OI Wiki)
介绍:这个定理是一个关于最大公约数的定理,用于快速求解两数的最大公约数。
代码
int gcd(int a, int b) // 欧几里得算法
{
return b ? gcd(b, a % b) : a;
}
拓展
扩展欧几里得算法:此算法的原理与线性同余方程 - OI Wiki是相同的看这一篇就行了。
代码:
int exgcd(int a, int b, int &x, int &y) // 扩展欧几里得算法, 求x, y,使得ax + by = gcd(a, b)
{
if (!b)
{
x = 1; y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
最小公倍数:这是与最大公约数相对应的概念,与其相关的定理是“a与b的最大公约数与最小公倍数的乘积等于a与b的乘积”。
约数定理(约数个数定理,约数和定理):用来求解约数个数和约数和的定理。定理的说明在链接里非常详细,在具体执行代码的过程中,还需要用到分解质因数。代码链接:分解质因数_百度百科 (baidu.com)。
//约数个数定理
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 2050;// n以内的质数
bool st[N];
int cnt = 0,prime[N];
void get_primes(){
for(int i = 2; i <= 2020; i++)
{
if(!st[i])
prime[cnt++] = i;
for(int j = 0; prime[j] <= 2020 / i; j++)
{
st[prime[j] * i] = true;
if(i % prime[j] == 0)
break;
}
}
}//筛质数
int factor_count(int n){
int ans = 1,sum;
for(int i = 0; prime[i] < n / prime[i]; i++){
if(n % prime[i] == 0){
sum = 0;
while(n % prime[i] == 0){
sum++;
n /= prime[i];
}
ans *= (sum+1);
}
}
if(n > 1)
ans *= 2;
return ans;
}
int main()
{
int n;
get_primes();
cin >> n;
cout <<factor_count(n);
return 0;
}
//约数和定理
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 2050;// n以内的质数
bool st[N];
int cnt = 0,prime[N],MOD = 1000000;//要%的数
void get_primes(){
for(int i = 2; i <= 2020; i++)
{
if(!st[i])
prime[cnt++] = i;
for(int j = 0; prime[j] <= 2020 / i; j++)
{
st[prime[j] * i] = true;
if(i % prime[j] == 0)
break;
}
}
}//筛质数
int pow_mod(int a,int n,int MOD){
int ans = 1;
while(n){
if(n&1)
ans = (ans*a)%MOD;
n >>= 1;
a = (a*a)%MOD;
}
return ans;
}
int factor_sum(int n){
int ans = 1,sum;
for(int i = 0; prime[i] < n / prime[i]; i++){
if(n % prime[i] == 0){
sum = 0;
while(n%prime[i] == 0){
sum++;
n /= prime[i];
}
ans *= (pow_mod(prime[i],sum+1,MOD)-1)/(prime[i]-1);
}
}
if(n > 1)
ans *= (n*n-1)/(n-1);
return ans;
}
int main()
{
int n;
get_primes();
cin >> n;
cout <<factor_sum(n);
return 0;
}
//分解质因数
#include <iostream>
using namespace std;
int main()
{
int n,n2;
cout<<"请输入需要分解的质因数:" ;
cin>>n;
cout<<n<<"=";//输出等于号
n2=n;
if(n<2){
return 0;//n小于2返回自身
}
cout<<"1*"; //输出 1*
for(int i=2;i*i<=n2;i++)//for循环穷举质因数
{
while(n2%i==0)//while循环判断质因数
{
n2=n2/i;//获得质因数
cout<<i;//返回质因数
if (n2!=1)//判断质因数
cout<<"*";//输出乘号
}
}
if(n2!=1){//判断质因数
cout<<n2;//输出质因数
}
return 0;//返回
}
//法2:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int m=n;
int flag=0;
cout<<m<<"=";
for(int i=2;i*i<=n;i++)
{
if(n%i==0)
{
int cnt=0;
while(n%i==0)
{
n=n/i;
cnt++;
}
if(flag==1) printf("*");
if(cnt==1)
{
printf("%d",i);
}
else
{
printf("%d^%d",i,cnt);
}
flag=1;
}
}
if(n>1)
{
if(flag==1)printf("*");
printf("%d",n);
}
return 0;
}
寻找质数
质数判断&分解质数&质数筛法 - AcWing:看这一篇就够了,筛法的时间复杂度是根号n。
#include <iostream>//质数相关的而题目要注意0,1这两个数
using namespace std;
const int N = 1010;
bool st[N];
int cnt = 0,prime[N];
void get_primes(int x){
for(int i = 2; i <= x; i++)
{
if(!st[i])
prime[cnt++] = i;
for(int j = 0; prime[j] <= x / i; j++)//“ 《= ”
{
st[prime[j] * i] = true;
if(i % prime[j] == 0)
break;
}
}
}
int main()
{
int n,sum = 0;
cin >> n;
get_primes(n);
for(int i = 2;i <= n;i ++)
if(!st[i]){
cout << i << " ";sum ++;
}
cout << endl;
cout << sum;
return 0;
}
快速幂
AcWing 875. 快速幂—含快速幂思想的解释 - AcWing
#include <iostream>
using namespace std;
const int N = 1010;
bool st[N];
int cnt = 0,prime[N];
void get_primes(int x){
for(int i = 2; i <= x; i++)
{
if(!st[i])
prime[cnt++] = i;
for(int j = 0; prime[j] <= x / i; j++)
{
st[prime[j] * i] = true;
if(i % prime[j] == 0)
break;
}
}
}
int main()
{
int n,sum = 0;
cin >> n;
get_primes(n);
for(int i = 2;i <= n;i ++)
if(!st[i]){
cout << i << " ";sum ++;
}
cout << endl;
cout << sum;
return 0;
}
求逆元
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
LL qmi(int a, int b, int p)
{
LL res = 1;
while (b)
{
if (b & 1) res = res * a % p;
a = a * (LL)a % p;
b >>= 1;
}
return res;
}
int main()
{
int n;
scanf("%d", &n);
while (n -- )
{
int a, p;
scanf("%d%d", &a, &p);
if (a % p == 0) puts("impossible");
else printf("%lld\n", qmi(a, p - 2, p));
}
return 0;
}