HDU4335 欧拉函数及降幂

求满足$n^{n!}\equiv b $(mod p)的n的数量。

思路:n!太大了,这一题要用到降幂公式:

A^x = A^(x % Phi(C) + Phi(C)) (mod C) (x>=Phi(C))

所以可以把n的取值分为三部分。

1:n≤phi(C),这部分直接暴力

2:当n!%phi(c)=0时,(n+1)!%phi(c)=0,这时公式可化为求A^(phi(c))

所以第二部分是n!%phi(c)!=0时,也是暴力。

3:最后一部分由于幂指数不变,根据鸽巢原理求出其循环节然后算出贡献。

 

注意特判P为1的情况(P为1时,m可能爆ull)

 

#include
#include
#include
#include
#include
#include
#include
#include
#include<string>
#define ll unsigned long long
#define PI acos(-1.0)
#define F first
#define S second
#define pb push_back
#define debug(x); printf("debug%lld\n",x);
#define des(x); printf("des:%s\n",x+1);
const ll INF=0x3f3f3f3f3f3f3f3f;
const int inf=0x3f3f3f3f;
//const ll mod=1e9+7;
ll mod;
using namespace std;
int t;
ll m,b,p;
const int N=1e5+5;
ll num[N];
ll oula(ll x)
{
    ll temp=x;
    for(ll i=2;i*i<=x;i++)
    {
        if(x%i==0)
        {
            temp=temp/i*(i-1);
            while(x%i==0)
            {
                x/=i;
            }
        }
    }
    if(x>1)
        temp=temp/x*(x-1);
    return temp;
}
ll QuickPow(ll x,ll N)
{
    ll res = x;
    ll ans = 1ll;
    while(N)
    {
        if(N&1)
        {
            ans=ans*res%mod;
        }
        res=res*res%mod;
        N=N>>1;
    }
    return ans;
}
int main()
{
    scanf("%d",&t);
    for(int tt=1;tt<=t;tt++)
    {
        scanf("%I64u%I64u%I64u",&b,&p,&m);
        printf("Case #%d: ",tt);
        ll phi=oula(p);
        mod=p;
        ll i=0;
        ll ans=0;
        ll fac=1;
        if(p==1)
        {
            if(m==18446744073709551615ll)
            {
                printf("18446744073709551616\n");
            }
            else
                printf("%I64u\n",m+1);
            continue;
        }
        for(i;i<=m&&fac<=phi;i++)
        {
            if(QuickPow(i,fac)==b)
            {
                ans++;
            }
            fac*=(i+1);
        }
        fac%=phi;
        for(i;fac&&i<=m;i++)
        {
            if(QuickPow(i,fac+phi)==b)
                ans++;
            fac=(fac*(i+1))%phi;
        }
        if(i<=m)
        {
            ll cnt=0;
            for(ll j=0;j)
            {
                num[j]=0;
                if(QuickPow(i+j,phi)==b)
                {
                    num[j]++;
                    cnt++;
                }
            }
            ll total=(m-i+1)/p;
            ans+=total*cnt;
            total=(m-i+1)%p;
            for(ll j=0;j)
            {
                if(num[j])
                    ans++;
            }
        }
        printf("%I64u\n",ans);
    }
    return 0;
}
View Code

 

你可能感兴趣的:(HDU4335 欧拉函数及降幂)