Acwing 第四章 数学知识
一、质数
866. 试除法判定质数
#include
#include
#include
using namespace std;
const int N = 105;
bool isprime(int x)
{
if(x<2) return false;
for(int i=2;i<=x/i;i++) //用i<=x/i多快好省,用sqrt(x)很慢,用i*i<=x可能爆int
{
if(x%i==0) return false;
}
return true;
}
int main()
{
int n,x;
cin>>n;
while(n--)
{
cin>>x;
if(isprime(x)) puts("Yes");
else puts("No");
}
return 0;
}
867. 分解质因数
#include
#include
#include
using namespace std;
void depart(int x)
{
for(int i=2;i<=x/i;i++) //n中最多只含有一个大于sqrt(n)的因子
//对其进行优化,先考虑比sqrt(n)小的
{
if(x%i==0) //i一定是质数
{
int s=0;
while(x%i==0)
{
x = x/i;
s++;
}
cout< 1) cout<1,说明这就是大于sqrt(n)的唯一质因子
puts("");
}
int main()
{
int n,x;
cin>>n;
while(n--)
{
cin>>x;
depart(x);
}
return 0;
}
线形筛素数法(埃筛法)
868. 筛质数
#include
#include
#include
using namespace std;
const int N = 1e6+10;
int n;
int prime[N],cnt; //素数数组及其个数
bool st[N]; //是否被筛除
void get_primes(int n) //埃式筛法
{
for(int i=2;i<=n;i++)
{
if(!st[i])
{
prime[cnt++] = i;
for(int j=i*2;j<=n;j+=i) //只将所有质数的倍数筛去
{
st[j] = true;
}
}
}
}
void get_primes(int n) //线性法
{
for(int i=2;i<=n;i++)
{
if(!st[i]) prime[cnt++] = i;
for(int j=0;prime[j] <= n/i;j++)
{
st[prime[j]*i] = true;
if(i % prime[j] == 0) break; //prime[j]一定是i的最小质因子
}
}
}
int main()
{
cin>>n;
get_primes(n);
cout<
二、约数
869. 试除法求约数
#include
#include
#include
using namespace std;
const int M = 105;
int n,x;
vectordivisior(int x)
{
vectorres;
for(int i=1;i<=x/i;i++)
{
if(x%i==0)
{
res.push_back(i);
if(x/i != i) res.push_back(x/i); //当遇到i为x的根号时,只能输出一次约数
}
}
sort(res.begin(),res.end());//题目要求结果有序
return res;
}
int main()
{
cin>>n;
while(n--)
{
cin>>x;
vector v = divisior(x);
for(auto t:v)
{
cout<
870. 约数个数
思路:对于每个因数,指数从0到α-1共α个供选择构成约数,故得到公式
#include
#include
#include
871. 约数之和
#include
#include
872. 最大公约数
#include
using namespace std;
typedef long long LL;
int n;
int a,b;
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
cin>>n;
while(n--)
{
cin>>a>>b;
cout<
三、欧拉函数
定义
873. 欧拉函数
#include
#include
#include
using namespace std;
int n,x;
int main()
{
cin>>n;
while(n--)
{
cin>>x;
int res = x;
for(int i=2;i<=x/i;i++)
{
if(x%i==0)//i是x的一个质因数
{
res = (res / i) * (i-1); //先除法后乘法,防止溢出
while(x%i==0)//除干净
{
x = x/i;
}
}
}
if(x>1) res = (res/x) *(x-1);//先除法后乘法,防止溢出
cout<
874. 筛法求欧拉函数
#include
#include
#include
using namespace std;
typedef long long LL;
const int N = 1e6+10;
int primes[N],cnt;
int phi[N];
bool st[N];
LL get_eulers(int n)
{
phi[1] = 1;
for(int i=2;i<=n;i++)
{
if(!st[i])
{
primes[cnt++] = i;
phi[i] = i-1;
}
for(int j=0;primes[j] <= n/i;j++)
{
st[primes[j]*i] = true;
if(i % primes[j] == 0)
{
phi[primes[j] * i] = phi[i] * primes[j];
break;
}
phi[primes[j] * i] = phi[i] * (primes[j] - 1);
}
}
LL res = 0;
for(int i = 1;i <= n;i++)
{
res += phi[i];
}
return res;
}
int main()
{
int n;
cin>>n;
cout<
四、快速幂
875. 快速幂
#include
#include
#include
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
LL a,k,p;
LL qmi(LL a,LL k,LL p) //a^k % p log(k)的时间内算出
{
LL res = 1;
while(k)
{
if(k&1) res = (LL)(res*a)%p;
k >>= 1;
a = (LL)(a * a) % p;
}
return res;
}
int main()
{
int n;
cin>>n;
while (n -- )
{
scanf("%lld%lld%lld", &a, &k,&p);
cout<
876. 快速幂求逆元
a/b mod p 相当于 a*(power(a,p-2) mod p)
#include
#include
#include
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
LL qmi(LL a,LL b,LL p)
{
LL res = 1;
while(b)
{
if(b&1) res = (LL)(res*a)%p;
b >>= 1;
a = (LL)a*a%p;
}
return res;
}
int n;
LL a,p;
int main()
{
scanf("%d",&n);
while(n--)
{
scanf("%lld%lld", &a, &p);
LL t = qmi(a,p-2,p);
if(a%p) cout<
五、扩展欧几里得
877. 扩展欧几里得算法
#include
#include
#include
using namespace std;
const int N = 1e5 + 10;
int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x = 1,y = 0;
return a;
}
int d = exgcd(b,a%b,y,x);
y -= a/b * x;
return d;
}
int n,a,b,x,y;
int main()
{
scanf("%d", &n);
while (n -- )
{
scanf("%d%d", &a, &b);
exgcd(a,b,x,y);
cout<