hdu5728PowMod

来源:互联网 发布:162端口 编辑:程序博客网 时间:2024/06/06 01:51

题目:

给定 n,m,p

先得到   k=mi=1φ(in) mod 1000000007

k=mi=1φ(in) mod 1000000007

其中n为非平方数

再计算ans=kkkk...k mod p

这里有无穷个k

思路:

1。求k

欧拉函数是非完全积性函数,φ(a*b)=φ(a)*φ(b),当gcd(a,b)=1;

φ(i*n)=φ(a)*φ(b)     a*b=i*n     gcd(a,b)=1;

遍历出一个n的约数

显然第一次遍历到的是一个素数p,并且是n的最小素因子

利用   φ(a*b)=φ(a)*φ(b),当gcd(a,b)=1; p和(n/p) 互素        mi=1φ(in)= φ(p)* mi=1φ(i∗n/p)

似乎不太对, p和(n/p) 互素  ,但是 p和i不一定互素

p和i不互素时 ,此时的i=kp,并且p是一个质数

φ(in)=p*φ(in/p)

前面的φ(p)* mi=1φ(i∗n/p)已经 加上了 φ(p)个 [即p-1个]φ(in/p)

也即  mi=1φ(in)= φ(p)* mi=1φ(i∗n/p) +  φ(in/p)

  φ(in/p)中,i=kp  ,  φ(in/p)=  φ(kn)    ,k=1,2,.....,m/p

即最后

∑(i=1,m)φ(i*n) = φ(pi) * ∑(i=1,m)φ(i*n/pi) + ∑(i=1,m/pi)φ(i*n) ;

这样k便可以递归的求出来了

2。求ans

我们知道欧拉定理得到的 指数循环节: A^x = A^(x % φ(C) + φ(C)) (mod C)  (x >= φ(C))

ans=k^k....(mod c) = k^(k^k... % φ(C) + φ(C)) (mod C)  (k^k...... >= φ(C))

而其中的k^k^k^k... % φ(C)

又可以为 ans'=k^k..... (modφ(C) )= k^(k^k... %φ(φ(C)) + φ(φ(C))) (modφ(C))  (k^k...... >= φ(C))

往下递归下去

φφφφφφφφφφφ (C)会收敛到1

任何数mod1都为 0可以结束递归返回快速幂的答案

#include<bits/stdc++.h>using namespace std;//const int M =10000010,N=1000000007 ;const int M = 1e7 + 5 ;const int N = 1e9 + 7 ;int prime[M],euler[M],s[M];int res;int n,m,p;void init(){res=0;euler[1]=1;for(int i=2;i<M;i++){if(!euler[i]){ prime[res++]=i; euler[i]=i-1;}for(int j=0;j<res&&i*prime[j]<M;j++){if(i%prime[j]==0)            {                euler[prime[j]*i]=euler[i]*prime[j];                break;            }            euler[prime[j]*i]=euler[i]*(prime[j]-1);}}for(int i=1;i<M;i++)s[i]=(euler[i]+s[i-1])%N;}long long qu(long long a,long long b,long long p){long long  ans=1;a=a%p;while(b){if(b&1) ans=(ans*a)%p;b>>=1;a=(a*a)%p;}return ans%p;}long long f(long long k,long long p){   if(p==2) return 0;return qu(k,f(k,euler[p])+euler[p],p);}long long ans(long long n,long long m){    if( m < 1 ) return 0 ;    if( m == 1 ) return euler[n];    if( n == 1 ) return s[m] ;    if( euler[n] == n-1 )  return ( ans(1,m) * (n-1) % N+ ans(n,m/n) ) % N ;     for( int i = 2 ; i*i <= n ; i++ )    {        if( n%i ) continue ;        return ((i-1)* ans(n/i,m) % N+ ans(n,m/i) ) % N ;    } }int main(){init();while(~scanf("%d%d%d",&n,&m,&p)) cout<< f(ans(n,m),p)<<endl;return 0;}


原创粉丝点击