质数(prime) 从2开始的整数,且其约数只有1和自己本身。
质数的判定 试除法 O(sqrt(n))
#include<bits/stdc++.h>
using namespace std;
int n;
int Prime(int x){
if (x < 2) return 0; 特判!! 小于2则不是!!
for(int i=2;i<=x/i;i++){ !!! i<=x/i
if(x%i==0) return 0;
}
return 1;
}
int main(){
cin>>n;
while(n--){
int x; cin>>x;
if(Prime(x)) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
分解质因数 试除法 试除法 O(sqrt(n)) 最好O(logn)
#include<bits/stdc++.h>
using namespace std;
int n;
void divide(int x){
for(int i=2;i<=x/i;i++){
if(x%i==0){
int cnt=0; 存指数
while(x%i==0){
x/=i;
cnt++;
}
cout<<i<<" "<<cnt<<endl;
}
}
if(x>1) cout<<x<<" "<<1<<endl; 最多只能存在一个大于Sqrt(n)的质因数
}
int main(){
cin>>n;
while(n--){
int x;
cin>>x;
divide(x);
}
}
筛质数 一般用线性筛法
埃式筛法O(nloglogn) 了解思想:筛质数的倍数
思想是: 从小到大枚举数字,筛掉质数的倍数 , 未被筛的就是质数
#include <iostream>
#include <algorithm>
using namespace std;
const int N= 1000010;
int primes[N], cnt; primes存序列中的所有质数
bool st[N]; x被筛,即x为合数,则st[x]等于1
void get_primes(int n)
{
for (int i = 2; i <= n; i ++ )
{
if (st[i]) continue; 被筛了 不考虑
primes[cnt ++ ] = i; 未被筛 是质数
for (int j = i + i; j <= n; j += i) !!筛掉质数的倍数
st[j] = true;
}
}
int main()
{
int n;
cin >> n;
get_primes(n);
cout << cnt << endl;
return 0;
}
线性筛法 O(N) 每个数都由其最小质因数筛掉
每个合数都有多个质因子,但只有一个最小质因子,所以可以保证只筛一遍即可
重点在break
如果不break,当第一次 i 整除 primes[0] 后,由于 i 是由 primes[0] 乘以其他数得到,所以 primes[1] * i 可以转化为 primes[0] * 其他数,所以此时 primes[1] 不是最小质因子
#include<bits/stdc++.h>
using namespace std;
int n;
const int N=1000010;
int primes[N],cnt;
int ST[N];
void get_prime(int n){
for(int i=2;i<=n;i++){ 从2开始循环这个序列
if(!ST[i]) primes[cnt++]=i; 未被筛 则加入质数数组
for(int j=0;primes[j]<=n/i;j++){ 从小到大循环已知的质数
ST[primes[j]*i]=1; 保证primes是primes[j]*i的最小质数
if(i%primes[j]==0) break;
}
}
}
int main(){
cin>>n;
get_prime(n);
cout<<cnt;
}
约数(因数) O(sqrt(n)
求约数 试除法(都是成对出现)
#include<bits/stdc++.h>
using namespace std;
int n;
vector<int> get_divisors(int a){
vector<int> v;
for(int i=1;i<=a/i;i++){
if(a%i==0){
v.push_back(i);
if(i!=a/i) v.push_back(a/i);
}
}
sort(v.begin(),v.end());
return v;
}
int main(){
cin>>n;
while(n--){
int a; cin>>a;
auto answer=get_divisors(a);
for(auto t:answer) cout<<t<<" ";
cout<<endl;
}
}
某数的约数个数、约数之和
先得到分解质因数的形式
求个数 涉及求乘积的约数
#include<bits/stdc++.h>
using namespace std;
int mod=1e9+7;
int main(){
int n; cin>>n;
unordered_map<int,int> primes;
while(n--){
int x; cin>>x;
for(int i=2;i<=x/i;i++){
if(x%i==0){
while(x%i==0){
primes[i]++;
x/=i;
}
}
}
if(x>1) primes[x]++;
}
long long res=1;
for(auto prime:primes){
res=res*(prime.second+1)%mod; 模对加法 乘法都有分配律
}
cout<<res;
}
约数求和
#include<bits/stdc++.h>
using namespace std;
int mod=1e9+7;
int main(){
int n; cin>>n;
unordered_map<int,int> primes;
while(n--){
int x; cin>>x;
for(int i=2;i<=x/i;i++){
if(x%i==0){
while(x%i==0){
primes[i]++;
x/=i;
}
}
}
if(x>1) primes[x]++;
}
long long res=1;
for(auto prime:primes){
long long t=1;
int p=prime.first; int a=prime.second;
while(a--) t=(t*p+1)%mod; 等比数列求和
res=(res+t)%mod;
}
cout<<res;
}
最大公约数 辗转相除法
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}