上帝与集合的正确用法(欧拉定理)

洛古

前置之士:欧拉定理和拓展欧拉定理:

(a^bequiv a^{b mod φ (m)} qquadqquad gcd(a,m)=1)

(a^bequiv a^b qquadqquadqquadqquad gcd(a,m) eq 1,b<φ (m))

(a^bequiv a^{(b mod φ (m))+φ (m)} qquad gcd(a,m) eq 1,bge φ (m))

然后我们发现,(p)是随即数据,不把保证(p,a)互质,所以我们用上述后两个结论,也就是拓展欧拉定理。

于是我们可以递归执行,直到模数为0,返回1即可

但是我们发现随着递归的深入,我们的模数也在变,所以我们要预处理出所有的(φ)值,我们可以用线性筛(主要是Eratosthenes筛法TLE了)来预处理

代码如下:

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define re register
#define debug printf("Now is Line : %d
",__LINE__)
#define file(a) freopen(#a".in","r",stdin);freopen(#a".out","w",stdout)
#define ll long long
il int read()
{
    re int x=0,f=1;re char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
    return x*f;
}
#define maxn 10000000
int n,m,f[maxn+5],p[5000000],tot;
bool is[maxn+5];
il ll quickpow(ll a,int b,int mod)
{
    ll r=1;
    while(b)
    {
        if(b&1) r=(r*a)%mod;
        b>>=1;
        a=(a*a)%mod;
    }
    return r;
}
il ll solve(int mod)
{
    if(mod==1) return 0;
    return quickpow(2,solve(f[mod])+f[mod],mod);
}
signed main()
{
    f[1]=1;
    for(re int i=2;i<=maxn;++i)
    {
        if(!is[i]) p[++tot]=i,f[i]=i-1;
        for(re int j=1;j<=tot;++j) 
        {
            if(i*p[j]>maxn) break;
            is[i*p[j]]=1;
            if(i%p[j]) f[i*p[j]]=f[i]*(p[j]-1);
            else {f[i*p[j]]=f[i]*p[j];break;}
        }
    }
    int T=read();
    while(T--)
    {
        n=read();
        printf("%lld
",solve(n));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/bcoier/p/10331751.html