1. 程式人生 > 實用技巧 >洛谷 U137412 高斯的小宇宙

洛谷 U137412 高斯的小宇宙

洛谷 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\n",gcd(a,p));
        }
        else if(opt==2)
        {
            scanf("%lld",&p);
            printf("%lld\n",lcm(a,p));
        }
        else if(opt==3)
            printf("%lld\n",isprime(a));
        else if(opt==4)
            printf("%lld\n",euler_prime(a));
        else if(opt==5)
            printf("%lld\n",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\n",inv[a]);
        }
    }
    return 0;
}