质数
一个大于 1 的自然数,如果除了 1 和它自身外,不能被其他自然数整除则称该数为质数。
试除法判定质数
#include <iostream>
using namespace std;
bool is_prime(int x)
{
if (x<2) return false;
for (int i=2;i<=x/i;i++)//i*i<=x会溢出
if (x%i==0) return false;
return true;
}
int main()
{
int n;
cin>>n;
while(n--)
{
int x;
cin>>x;
if (is_prime(x)) cout<<x<<" "<<"is prime"<<endl;
else cout<<x<<" "<<"is not prime"<<endl;
}
}
质因数分解
将每个数分解质因数,并按照质因数从小到大的顺序输出每个质因数的底数和指数。
输入样例:
2
6
8
输出样例:
2 1
3 1
(空行)
3 1
#include <iostream>
using namespace std;
void divide(int x)
{
for (int i=2;i<=x/i;i++)
if (x%i==0)
{
int s=0;
while(x%i==0) x/=i, s++;
cout<<i<<' '<<s<<' '<<endl;
}
if (x>1) cout<<x<<' '<<1<<endl;//较大的一个素数
}
int main()
{
int n;
cin>>n;
while(n--)
{
int x;
cin>>x;
divide(x);
cout<<endl;
}
}
朴素筛法求素数
#include <iostream>
using namespace std;
const int N=1e6+10;
int cnt;
bool st[N];//判断是否被筛掉
void get(int n)
{
for (int i=2;i<=n;i++)
{
if (st[i]) continue;
else
{
cnt++;
for (int j=i+i;j<=n;j+=i)
st[j]=true;
}
}
}
int main()
{
int n;
cin>>n;
get(n);
cout<<cnt<<endl;
}
线性筛法求素数
#include <iostream>
using namespace std;
const int N=1e8+10;
int cnt;
int prime[N];//存储所有素数
bool st[N];//判断是否被筛掉
void get(int n)
{
for (int i=2;i<=n;i++)
{
if (st[i]==0)
{
prime[cnt]=i;
cnt++;
}
for (int j=0;prime[j]<=n/i;j++)
{
st[prime[j]*i]=true;
if (i%prime[j]==0) break;//防止重复筛掉
}
}
}
int main()
{
int n;
cin>>n;
get(n);
cout<<cnt<<endl;
}
约数
试除法求约数
一共n个正整数,从小到大输出每个数ai的所有约数
1<=n<=100
2<=ai<=2*10^9
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=2e6+10;
int prime[N];
void get(int n)
{
memset(prime, 0, sizeof prime);
int idx=0;
for (int i=1;i<=n/i;i++)
{
if (n%i==0) prime[idx++]=i;
if (i!=n/i) prime[idx++]=n/i;
}
sort(prime,prime+idx);
for (int i=0;i<idx;i++)
{
cout<<prime[i]<<' ';
}
cout<<endl;
}
int main()
{
int n;
cin>>n;
while (n--)
{
int x;
cin>>x;
get(x);
}
}
约数个数和约数之和
N=p1^c1 * p2^c2 * … * pk^ck
约数个数:(c1+1) * (c2+1) * … * (ck+1)
约数之和:(p1^0 + p1^1 + … +p1^c1) * … * (pk^0 +pk^1 + … pk^ck)
约数个数
给定n个正整数ai ,输出这些数的乘积的约数个数,答案对1e9+7取模
1<=n<=100
1<=ai<=2*10^9
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int mod=1e9+7, N=1e8+10;
int b[N];//存储指数
LL cnt=1;
int main()
{
int n;
cin>>n;
int maxx=0;
while(n--)
{
int x;
cin>>x;
for (int i=2;i<=x/i;i++)
{
while(x%i==0)
{
x/=i;
b[i]++;
maxx=max(maxx,i);
}
}
if (x>1) b[x]++, maxx=max(maxx,x);
}
for (int i=0;i<=maxx;i++)
if (b[i]) cnt=cnt*(b[i]+1)%mod;
cout<<cnt;
}
约数之和
给定n个正整数ai ,输出这些数的乘积的约数之和,答案对1e9+7取模
1<=n<=100
1<=ai<=2*10^9
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int mod=1e9+7, N=1e8+10;
int b[N];//存储底数和指数,b[i]=j,i为底数,j为指数
LL sum=1;
int main()
{
int n;
cin>>n;
int maxx=0;
while(n--)
{
int x;
cin>>x;
for (int i=2;i<=x/i;i++)
{
while(x%i==0)
{
x/=i;
b[i]++;
maxx=max(maxx,i);
}
}
if (x>1) b[x]++, maxx=max(maxx,x);
}
for (int i=0;i<=maxx;i++)
{
if (b[i])
{
LL t=1;
while(b[i]--)
{
t=(t*i+1)%mod;
}
sum=sum*t%mod;
}
}
cout<<sum;
}
欧拉函数
欧几里得算法
#include <iostream>
using namespace std;
int gcd(int a, int b)
{
return b ? gcd(b,a%b) : a;
}
int main()
{
int a,b;
cin>>a>>b;
cout<<gcd(a,b);
}
求欧拉函数
欧拉函数:1到n中与n互质的数的个数
n分解质因数:n=p1^c1 * p2^c2 * … * pk^ck
则个数为 n * (1-1/p1) * (1-1/p2) * … * (1-1/pk)
给定n个正整数ai,求每个数的欧拉函数
1<=n<=100
1<=ai<=2*10^9
#include <iostream>
using namespace std;
int phi(int x)
{
int res=x;
for (int i=2;i<=x/i;i++)
{
if (x%i==0)
{
res=res/i*(i-1);
while(x%i==0) x/=i;
}
}
if (x>1) res=res/x*(x-1);
return res;
}
int main()
{
int n;
cin>>n;
while(n--)
{
int x;
cin>>x;
cout<<phi(x)<<endl;
}
}
筛法求欧拉函数
求1-n中每个数的欧拉函数之和
1<=n<=10^6
#include <iostream>
using namespace std;
typedef long long LL;
const int N=1e6+10;
int n;
int prime[N],cnt;//prime[]存储所有素数
int euler[N];//存储每个数的欧拉函数
bool st[N];
void get_euler(int n)
{
euler[1]=1;
for (int i=2;i<=n;i++)
{
if (st[i]==false)
{
prime[cnt++]=i;
euler[i]=i-1;//质数的欧拉函数
}
for (int j=0;prime[j]<=n/i;j++)
{
int t=prime[j]*i;
st[t]=true;
if (i%prime[j]==0)
{
euler[t]=euler[i]*prime[j];
break;
}
euler[t]=euler[i]*(prime[j]-1);
}
}
}
int main()
{
int n;
cin>>n;
get_euler(n);
LL ans=0;
for (int i=1;i<=n;i++)
ans+=euler[i];
cout<<ans;
}
快速幂
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long LL;
LL qmi(LL a, LL b, LL p)
{
LL res=1%p, base=a;
while(b)
{
if (b & 1) res=res*base%p;
base=base*base%p;
b>>=1;
}
return res;
}
int main()
{
LL a,b,p;
scanf("%lld%lld%lld",&a,&b,&p);
printf("%lld^%lld mod %lld=",a,b,p);
printf("%lld",qmi(a,b,p));
}
扩展欧几里得算法
题目描述
给定n对正整数ai,bi,对于每对数,求出一组xi,yi,使其满足aixi+biyi=gcd(ai,bi)。
输入格式
第一行包含整数n。
接下来n行,每行包含两个整数ai,bi。
输出格式
输出共n行,对于每组ai,bi,求出一组满足条件的xi,yi,每组结果占一行。本题答案不唯一,输出任意满足条件的xi,yi均可。
数据范围
1≤n≤10^5
1≤ai,bi≤2∗10^9
输入样例:
2
4 6
8 18
输出样例:
-1 1
-2 1
#include <iostream>
#include <algorithm>
using namespace std;
int exgcd(int a, int b, int &x, int &y)//返回x,y的值
{
if (b==0)
{
x=1,y=0;
return a;
}
int d=exgcd(b, a%b, x, y);
int temp=x;
x=y;
y=temp-(a/b)*y;
return d;
}
int main()
{
int n;
cin>>n;
while(n--)
{
int a,b,x,y;
cin>>a>>b;
exgcd(a,b,x,y);
cout<<x<<' '<<y<<endl;
}
}
本文介绍了多种数论算法,包括质数判断(试除法)、质因数分解、素数筛法(朴素筛法、线性筛法)以及与约数相关的计算,如求约数、约数个数、约数之和、欧拉函数等。同时,还涉及了最大公约数的计算和扩展欧几里得算法的应用。
2112

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



