1:数的表示
任何一个数都可以表示成下面的形式
N=p1^a1 * p2^a2 * p2^a2 * p2^a2......pn^an
1.pn表示质因子
2.an表示质因子的次幂
2:质数
a.质数的判断
//如果x|i,那么x|(x/i),如6/2=3,6/3=2,所以判断的时候只需要判断小的数就可以。
bool is_prime(int x)
{
if(x==1) return false;
if(x==2) return true;
for(int i=2;i<=x/i;i++)
{
if(x%i==0) return false;
}
return true;
}
b.分解质因子
//需要注意x有且只有一个大于sqrt(n)的因子
//可以用k++的数组保存质数,或者用unordered_map保存质数和个数
void div_prime(int x)
{
for(int i=2;i<=x/i;i++)
{
if(x%i==0)
{
int res=0;
while(x%i==0)
{
res++;
x/=i;
}
cout<<i<<' '<<res<<endl;
}
}
if(x!=1) cout<<x<<' '<<1<<endl;
}
c.筛质数
//方案一:埃氏筛法
void pri(int x)
{
for(int i=2;i<=x;i++)
{
if(book[i]%2==0)
{
p[idx++]=i;
for(int j=2*i;j<=x;j+=i)
{
book[j]=1;
}
}
}
}
//方案二:线性筛法
//可以顺便求出1-n的欧拉函数
void pri(int x)
{
for(int i=2;i<=x;i++)
{
if(book[i]==0) p[idx++]=i;
for(int j=0;p[j]<=x/i;j++)
{
book[p[j]*i]=1;
if(i%p[j]==0) break;
}
}
}
3:约数
a.试处法求约数
/*
约数满足 x|i x|(x/i) 所以只需要判断小于sqrt(x)的数就可以,
存储,数组,vector,优先队列都可以
*/
void div(int x)
{
a.clear();
for (int i = 1; i <= x / i; i++)
{
if (x % i == 0)
{
a.push_back(i);
if (i * i != x) a.push_back(x / i);
}
}
sort(a.begin(),a.end());
for(int i=0;i<a.size();i++) cout<<a[i]<<' ';
cout<<endl;
}
b.求约数的个数
//首先有定理 约数个数 N=(a1+1)*a(2+1)*...*(an+1)
//分解质因子然后计算 不开longlong见祖宗
#include<iostream>
#include <unordered_map>
using namespace std;
int const N = 1e9+7;
unordered_map<int,int> map;
int main()
{
int t; cin>>t;
while(t--)
{
int n; cin>>n;
for(int i=2;i<=n/i;i++)
{
if(n%i==0)
{
int res=0;
while(n%i==0)
{
res++;
n/=i;
}
map[i]+=res;
}
}
if(n!=1) map[n]++;
}
long long sum=1;
for(auto x:map)
{
sum=sum*(x.second+1)%N;
}
cout<<sum<<endl;
}
c.求约数的和
//约数和的定理
//( t=(t*p+1))
#include<iostream>
#include<queue>
#include<unordered_map>
using namespace std;
int const INF = 1e9+7;
unordered_map<int,int> map;
void pri(int x)
{
for(int i=2;i<=x/i;i++)
{
if(x%i==0)
{
int res = 0;
while(x%i==0)
{
res++;
x/=i;
}
map[i]+=res;
}
}
if(x!=1) map[x]++;
}
int main()
{
int n; cin>>n;
for(int i=1;i<=n;i++)
{
int x; cin>>x;
pri(x);
}
long long res = 1;
for(auto x:map)
{
int p = x.first;
int a = x.second;
long long sum = 1;
while(a--)
{
sum=(sum*p+1)%INF;
}
res=res*sum%INF;
}
cout<<res<<endl;
}
d.最大公约数,最小公倍数
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}
4:欧拉函数
//欧拉函数定义1-n互质的个数
//phi(x) = x * (1-p1) * (1-p2) * (1-p3) * ...... * (1-pk)
求n的欧拉函数
//分解n的质因子然后遍历
#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_map>
using namespace std;
unordered_map<int, int> map;
void pri(int x)
{
for (int i = 2; i <= x / i; i++)
{
if (x % i == 0)
{
int res = 0;
while (x % i == 0)
{
res++;
x /= i;
}
map[i] += res;
}
}
if (x != 1) map[x]++;
}
int main()
{
int t; cin >> t;
while (t--)
{
map.clear();
int x; cin >> x;
pri(x);
long long sum = x;
for(auto x:map)
{
sum=sum/x.first*(x.first-1);
}
cout<<sum<<endl;
}
}
线性筛求欧拉函数
//可以求出1-n所有欧拉函数时间复杂度o(N)
#include<iostream>
using namespace std;
int const N = 1e6+10;
int p[N],idx;
int book[N];
int ol[N];
void pri(int n)
{
ol[1]=1;
for(int i=2;i<=n;i++)
{
if(book[i]==0)
{
p[idx++] = i;
ol[i]=i-1;
}
for(int j=0;p[j]<=n/i;j++)
{
book[p[j]*i]=1;
if(i%p[j]==0)
{
ol[p[j]*i]=ol[i]*p[j];
break;
}
else
{
ol[p[j]*i]=ol[i]*(p[j]-1);
}
}
}
}
int main()
{
int n; cin>>n;
pri(n);
long long sum=0;
for(int i=1;i<=n;i++) sum+=ol[i];
cout<<sum<<endl;
}
5.快速幂
LL res = 1;
while(k)
{
if(k&1) res=res*a%p;
a=a*a%p;
k>>=1;
}