1.质数:在大于1的整数中,只包含1和本身这两个约数,就被称为质数,或者素数。
1) 质数的判定 -试除法
bool is_prime(int x)
{
if(x<2) return false;
for(int p=2;p<x/p;p++)
if(x%p==0) return false;
return true;
}
2) 分解质因数
void divide (int x)
{
for(int p=2;p<=x/p;p++) // 写成p<=x/p 的原因是 防止数据溢出
{
if(x%p==0)
{
int s=0;
while(x%p==0)
{
x/=p;
s++;
}
cout<<p<<" "<<s<<endl;
}
}
if(x>1) cout<<x<<" "<<"1"<<endl; // 最多存在一个大于x 的质因子 如果 有两个那么相乘大于x 了 显然不成立
}
3)质数筛选
1.埃氏筛法
void isprime(int x) // cnt 为质数个数
{
for(long long p=2;p<=x;p++)
{
for(long long i=p*p;i<=x;i+=p)
{
if(!st[i]) st[i]=true;
}
if(!st[p]) primes[cnt++]=p;
}
}
2.欧拉筛
void get_prime(long long x)
{
for(long long p=2;p<=x;p++)
{
if(!st[p]) prime[cnt++]=p;
for(long long s=0;prime[s]<=x/p;s++)
{
st[prime[s]*p]=true;// 用最小的质因子筛去合数
if(p%prime[s]==0) break;// 1)当p%prime[s] !=0 的时候 prime[s] 不是 p 的最小质因子,只能是ps*p的最小质因子
// 2)当p%prime[s] ==0 的时候,prime[s] 是 p 的最小质因子,接下来用prime[s+1] 筛去prime[s+1]*p
但是 prime[s]<prime[s+1] 所以最小质因子 应该为prime[s] 避免重复筛去 退出循环
}
}
}
2.约数
约数的定义:如果一个整数能被两个整数整除,那么这两个数就是这个数的约数。
1)试除法求一个数的所有约数
vector<int> solve(int x)
{
vector<int>a;
for(int p=1;p<=x/p;p++)
{
if(x%p==0)
{
a.push_back(p);
if(p!=x/p)a.push_back(x/p);// 例如 4 / 2 =2 会放入 两个相同的元素
}
}
return a;
}
2)约数个数
公式:
#include <iostream>
#include <unordered_map> // 约数个数 (a1+1)*(a2+1)*(a3+1)···*(an+1);
using namespace std;
const int N =100010;
const long long mod=1e9+7;
unordered_map<int,int>primes;
void solve(int x)
{
for(int p=2;p<=x/p;p++)
{
while(x%p==0)
{
x/=p;
primes[p]++;
}
}
if(x>1) primes[x]++;
}
int main()
{
int n;
cin>>n;
int x;
while(n--)
{
cin>>x;
solve(x);
}
long long ans=1;
for(auto prime:primes) ans=ans*(prime.second+1)%mod;// 在计算的时候取模 防止 爆数据
cout<<ans<<endl;
return 0;
}
3)约数之和
公式:
#include <iostream>
#include <unordered_map>// 约数之和(p0+p1+`````+pn2)*(p1+````pn1)*````*(p1+````+pnn)
using namespace std;
unordered_map<int,int>primes;
const int mod =1e9+7;
void solve(int x)
{
for(int p=2;p<=x/p;p++)
{
while(x%p==0)
{
x/=p;
primes[p]++;
}
}
if(x>1) primes[x]++;
}
int main()
{
int n;
cin>>n;
int x;
while(n--)
{
cin>>x;
solve(x);
}
long long ans=1;
for(auto prime:primes)
{
int p=prime.first;int a=prime.second;
long long t=1;
while(a--) t=(p*t+1)%mod; // 求 (p0+p1+`````+pn2)*(p1+````pn1)*````*(p1+````+pnn) 技巧
ans=ans*t%mod;
}
cout<<ans<<endl;
}
3.gcd(辗转相除法)
int gcd(int a,int b)// 一行代码 gcd
{
return b?gcd(b,a%b):a; // 三目运算符的用法 ':'前面是否问真,若真 执行':' 后面 ‘:’ 前面,否则 执行‘;’后面
}
试题:AcWing 872. 最大公约数