(HDU 5728)2016 Multi-University Training Contest 1 PowMod(数论)

来源:互联网 发布:mac系统安装flash 编辑:程序博客网 时间:2024/05/16 05:32

思路

其实我并不知道要怎么做..
官方题解

代码

#include <bits/stdc++.h>#define mem(a,b) memset(a,b,sizeof(a))#define rep(i,a,b) for(int i=a;i<b;i++)#define debug(a) printf("a =: %d\n",a);const int INF=0x3f3f3f3f;const int maxn=1e7+50;const int Mod=1e9+7;const double PI=acos(-1);typedef long long ll;using namespace std;/*0.对于一个正整数n,小于n且和n互质的正整数(包括1)的个数,记作φ(n)φ(n)=n*(1-1/p1)*(1-1/p2)*(1-1/p3)*(1-1/p4)…..(1-1/pm),p为n的因子 (见initEuler())1.!! φ(1)=12.不完全积性函数:若m,n互质,φ(mn)=φ(m)φ(n)3.对于互质的正整数a和n,有aφ(n) ≡ 1 mod n4.当n为奇数时,φ(2n)=φ(n)5.若n是质数p的k次幂,φ(n)=p^k-p^(k-1)=(p-1)p^(k-1),因为除了p的倍数(一共n/p个)外,其他数都跟n互质。6.设a为N的质因数,若(N % a == 0 && (N / a) % a == 0) 则有E(N)=E(N / a) * a;若(N % a == 0 && (N / a) % a != 0) 则有:E(N) = E(N / a) * (a - 1) (见initPrimeAndEuler())*/int e[maxn];ll eSum[maxn]; //前缀和//初始化欧拉函数void initEuler(){     e[1]=1;     for(int i=2;i<maxn;i++)        e[i]=i;     for(int i=2;i<maxn;i++)        if(e[i]==i)           for(int j=i;j<maxn;j+=i)              e[j]=e[j]/i*(i-1);//先进行除法是为了防止中间数据的溢出}//直接计算欧拉函数int euler(int n){    int cnt=n;    for(int i=2;i<=n;i++)        if(n%i==0)  {            cnt-=cnt/i;      //   m-m/p            while(n%i==0)                n/=i;        }    return cnt;}bool notPrime[maxn];int prime[maxn];int cnt;//初始化素数表,是否素数(prime sieve)void initPrime(){    mem(notPrime,0);    cnt=0;    for(int i=2;i<maxn;i++){        if(notPrime[i]) continue;        prime[cnt++]=i;        for(int j=2*i;j<maxn;j+=i)            notPrime[j]=true;    }    notPrime[0]=notPrime[1]=1;}//初始化素数表,是否素数,欧拉函数void initPrimeAndEuler(){    cnt=0;    mem(notPrime,0);    e[1]=1;    for(int i=2;i<maxn;i++){        if (!notPrime[i]){            prime[cnt++]=i;            e[i]=i-1;        }        for(int j=0,k;j<cnt && (k=i*prime[j])<maxn;j++){            notPrime[k]=1;            if (i%prime[j]==0){                e[k]=e[i]*prime[j];                break;            }else {                e[k]=e[i]*(prime[j]-1);            }        }    }    notPrime[0]=notPrime[1]=1;}int n,m,p;int pn[maxn>>2];int pos;//求n的因子void getFac(int n){    pos=0;    for(int i=0;i<cnt;i++){        if (!notPrime[n]){            pn[pos++]=n;            break;        }        int pm=prime[i];        if (n%pm==0){            while(n%pm==0) {                pn[pos++]=pm;                n/=pm;            }        }    }}ll qPow(ll x,ll n,ll mod){    ll ret=1;    while(n){        if (n&1) ret=(ret*x)%mod;        x=(x*x)%mod;        n>>=1;    }    return ret;}ll cal_kkkk(ll a,ll p){    if (p==1) return 0;    ll tmp=cal_kkkk(a,e[p]); // b%phi(p)    ll ans=qPow(a,e[p]+tmp,p)%p;  //a^(phi(p)+b%phi(p)) %p    return ans;}ll cal_sum(int pos,ll n,ll m){    if (n==1) return eSum[m]; //sum(1,m)=sigma(eular(i))    if (m==0) return 0; //sum(n,0)=0;    //按照sum(n,m)=eular(p)*sum(n/p,m)+sum(n,m/p),计算,其中p为n分解出来的所有质数    //pn[pos]是素数,eular(p)=pn[pos]-1    ll l=(pn[pos]-1)*cal_sum(pos-1,n/pn[pos],m)%Mod;    ll r=cal_sum(pos,n,m/pn[pos]);    return (l+r)%Mod;}/*bool isprime(int n){    if (n<2) return 0;    for(int i=2;i*i<=n;i++){        if (n%i==0) return 0;    }    return 1;}*/int main(){    #ifndef ONLINE_JUDGE        freopen("in.txt","r",stdin);    #endif   // initEuler();   // initPrime();    initPrimeAndEuler();    eSum[0]=0;    for(int i=1;i<maxn;i++) eSum[i]=(eSum[i-1]+e[i])%Mod;    while(~scanf("%d %d %d",&n,&m,&p)){        getFac(n);        ll k=cal_sum(pos-1,n,m);        printf("%lld\n",cal_kkkk(k,p));    }    return 0;}
0 0