2016 Multi-University Training Contest 1 -1006 PowMod

来源:互联网 发布:美术字在线生成器软件 编辑:程序博客网 时间:2024/05/01 22:09

题目地址:hdu5728
http://acm.hdu.edu.cn/showproblem.php?pid=5728

PowMod

Problem Description

Declare:
k=mi=1φ(in) mod 1e9+7

n is a square-free number.

φ is the Euler’s totient function.

find:
ans=kkkk... mod p

There are infinite number of k

Input
Multiple test cases(test cases ≤100), one line per case.

Each line contains three integers, n,m and p.

1≤n,m,p≤107

Output
For each case, output a single line with one integer, ans.

Sample Input
1 2 6
1 100 9

Sample Output
4
7

题目大意:
给定n,m,p,
k=mi=1φ(in) mod 1e9+7,求kkk...mod p

另sum(n,m)=mi=1φ(in) mod 1e9+7
后面就不写取余啦!
假设 素数p 是n的一个约数,题目保证n为square-free number,即p2n.

sum(n,m)=i=1,pimφ(p)φ(inp)+T

这里p和inp互素,可以利用欧拉函数的积性展开。

T=mi=1,piφ(in)上面式子剩下的部分。
T=m/pi=1φ(ipn)
=m/pi=1φ(pk+1inpk) 保证pinpk
利用乘性展开:
=m/pi=1φ(pk+1)φ(inpk)
当p为素数时,φ(pk)=pkpk1
T=m/pi=1(pk+1pk)φ(inpk)
=m/pi=1φ(p)pkφ(inpk)
=m/pi=1φ(p)φ(inpk)(pkpk1+pk1)
=m/pi=1φ(p)φ(pk)φ(inpk)+m/pi=1φ(p)φ(inpk)(pk1)
=m/pi=1φ(p)φ(in)+m/pi=1φ(pk)φ(inpk)
=mi=1,piφ(p)φ(inp)+m/pi=1φ(in)

得到最终式子:

sum(n,m)=φ(p)sum(np,m)+sum(n,mp)

然后对于一对n,m,找到n的一个素因子递归求解即可。因为n<=1e7,n的素因子不超过8个。
本题寻找素因子过程暴力遍历素数表也可以过,我的方法是在线性筛的时候标记出每个数最大的素因子
求出k,后可以用欧拉降幂的公式递归求解:

ab=aφ(p)+bmodφ(p)modp(b>φ(p))

欧拉降幂的证明:
http://www.ithao123.cn/content-5288189.html

/* ***********************************************Author        :yuanzhaolinCreated Time  :2016年07月20日 星期三 08时51分40秒File Name     :f.cpp************************************************ */#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <sstream>#include <map>#include <string>#include <cmath>#include <stdlib.h>#include <time.h>#include <queue>#include <utility>using namespace std;#define repp(i,a,b) for(int i=a;i<=b;i++)#define rep(i,a) for(int i=0;i<a;i++)#define REP(i,a) for(int i=1;i<=a;i++)#define per(i,a,b) for(int i=a-1;i>=b;i--)#define foreach(i,a) for(int i=head[a];i>=0;i=ee[i].next)#define Foreach(i,a) for(__typeof((a).begin())i=(a).begin();i!=(a).end();i++)#define pb push_back#define all(x) (x).begin(),(x).end()#define mp make_pair#define m0(x) memset(x,0,sizeof(x))#define mff(x) memset(x,0xff,sizeof(x))#define fi first#define se second#define lson k<<1,l,(l+r)/2#define rson k<<1|1,(l+r)/2+1,r#define SZ(x) ((int)(x).size())#define sqr(x) ((x)*(x))#define C1(x) cout<<x<<endl#define C2(x,y) cout<<x<<" "<<y<<endl#define C3(x,y,z) cout<<x<<" "<<y<<" "<<z<<endltypedef long long ll;typedef vector<int> VI;typedef pair<int,int> PII;typedef vector< pair<int,int> > VPII;const ll mod=1e9+7;const ll maxn=1e7+7;const ll maxe=1e6+7;const ll INF=1e9+7;const double PI=acos(-1);int dx[4]={0,0,1,-1};int dy[4]={-1,1,0,0};long long qpow(long long a,long long n,long long mod){    long long ans=1;    while(n)    {        if(n&1) ans=ans*a%mod;        a=a*a%mod;        n>>=1;    }    return ans;}bool vis[maxn];int prime[maxe];int euler[maxn];long long esum[maxn];int cnt;int pri[maxn];void init(){    cnt=0;    euler[1]=1;    esum[1]=1;    for(int i=2;i<maxn;i++)    {        if(!vis[i])        {            prime[cnt++]=i;            euler[i]=i-1;            pri[i]=i;//i的最大的素因子        }        for(int j=0;j<cnt&&i*prime[j]<maxn;j++)        {            vis[i*prime[j]]=true;            pri[i*prime[j]]=pri[i];//i的最大的素因子            if(i%prime[j]==0)            {                euler[i*prime[j]]=euler[i]*prime[j];                break;            }            else                euler[i*prime[j]]=euler[i]*(prime[j]-1);        }    }    for(int i=1;i<maxn;i++)        esum[i]=(esum[i-1]+euler[i])%mod;}long long n,m,p;long long cal(long long n,long long m){    if(n==1ll) return esum[m]%mod;    if(m==1) return euler[n];    if(m<1ll) return 0ll;    int p=pri[n];    long long ans=1ll*(p-1)*cal(n/p,m)%mod+cal(n,m/p)%mod;    return ans%mod;}long long run(long long a,long long b){    long long ans;    if(b==1ll) ans=0;    else    {        long long tmp=run(a,euler[b]);        ans=qpow(a,tmp+euler[b],b);    }//    cout<<a<<" "<<b<<" "<<ans<<endl;    return ans;}void solve(){    long long k=cal(n,m);    long long tmp;    long long M=euler[p];    long long t=k%M;    long long ans=run(k,p);    cout<<ans<<endl;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    init();       while(cin>>n>>m>>p)    {        solve();    }    return 0;}
0 0