洛谷 U137412 高斯的小宇宙
题目背景
想必大家都听说过小高斯用高中数学必修五的知识爆锤小学老师的故事吧?现在,因为锤不过计算机,他来锤你了。
题目描述
高斯挑战评测姬失败之后,无奈地承认人力和姬力还是有很大的差距的。但是他又把矛头对准了所有学计算机的!你!义不容辞!
高斯要和你比拼算一些简单问题的能力。他要和你比算这些问题的能力:
1 a b 算gcd(a,b)gcd(a,b)
2 a b 算lcm(a,b)lcm(a,b)
3 a 判断a是否为质数
4 a 算从1到a有多少个质数
5 a 求a的欧拉函数phi(a)ϕ(a)
6 a p算出1-a在模p意义下的乘法逆元
7 a 算出1-a的欧拉函数
8 a 对a质因数分解
9 a p 算出a在模p意义下的乘法逆元
输入格式
输入的第一行是一个整数NN,表示高斯要跟你比赛NN场。之后的NN行,每行描述一个比赛,如上所述。
输出格式
输出NN行,第ii行表示你对第ii场比赛的答案。
题解:
数学大礼包狠狠砸中。
代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#define int long long
using namespace std;
const int maxn=1e8;
int n,cnt;
int prime[2000100],c[2000100],phi[2000100],inv[2000100];
bool v[maxn];
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int lcm(int a,int b)
{
return (a*b)/gcd(a,b);
}
int isprime(int a)
{
for(int i=2;i<=sqrt(a);i++)
if(a%i==0)
return 0;
return 1;
}
int euler_prime(int x)
{
cnt=0;
memset(v,0,sizeof(v));
for(int i=2;i<=x;i++)
{
if(!v[i])
prime[++cnt]=i,v[i]=1;
for(int j=1;j<=cnt && i*prime[j]<=x;j++)
{
v[i*prime[j]]=1;
if(i%prime[j]==0)
break;
}
}
return cnt;
}
int euler_fuc(int x)
{
cnt=0;
for(int i=1;i<x;i++)
if(gcd(i,x)==1)
cnt++;
return cnt;
}
void niyuan(int x,int p)
{
memset(inv,0,sizeof(inv));
inv[1]=1;
for(int i=2;i<=x;i++)
inv[i]=((p-p/i)*inv[p%i])%p;
}
void euler_go(int x)
{
cnt=0;
memset(v,0,sizeof(v));
for(int i=2;i<=x;i++)
{
if(!v[i])
prime[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt && i*prime[j]<=x;j++)
{
v[i*prime[j]]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else
phi[i*prime[j]]=phi[i]*phi[prime[j]];
}
}
}
void divide(int x)
{
cnt=0;
for(int i=2;i<=sqrt(x);i++)
{
if(x%i==0)
prime[++cnt]=i,c[cnt]=0;
while(x%i==0)
c[cnt]++,x/=i;
}
if(x>1)
prime[++cnt]=x,c[cnt]=1;
for(int i=1;i<=cnt;i++)
printf("%lld^%lld ",prime[i],c[i]);
puts("");
}
signed main()
{
scanf("%lld",&n);
while(n--)
{
int opt,a,p;
scanf("%lld%lld",&opt,&a);
if(opt==1)
{
scanf("%lld",&p);
printf("%lld
",gcd(a,p));
}
else if(opt==2)
{
scanf("%lld",&p);
printf("%lld
",lcm(a,p));
}
else if(opt==3)
printf("%lld
",isprime(a));
else if(opt==4)
printf("%lld
",euler_prime(a));
else if(opt==5)
printf("%lld
",euler_fuc(a));
else if(opt==6)
{
scanf("%lld",&p);
niyuan(a,p);
for(int i=1;i<=a;i++)
printf("%lld ",inv[i]);
puts("");
}
else if(opt==7)
{
euler_go(a);
for(int i=1;i<=a;i++)
printf("%lld ",phi[i]);
puts("");
}
else if(opt==8)
divide(a);
else
{
scanf("%lld",&p);
niyuan(a,p);
printf("%lld
",inv[a]);
}
}
return 0;
}