2016 Multi-University Training Contest 1 -1006 PowMod

题目地址: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        :yuanzhaolin
Created Time  :2016年07月20日 星期三 08时51分40秒
File Name     :f.cpp
************************************************ */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define repp(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,a) for(int i=0;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<
#define C2(x,y) cout<
#define C3(x,y,z) cout<
typedef 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;iif(!vis[i])
        {
            prime[cnt++]=i;
            euler[i]=i-1;
            pri[i]=i;//i的最大的素因子
        }
        for(int j=0;jtrue;
            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;i1]+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<
    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<int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    init();
       while(cin>>n>>m>>p)
    {
        solve();
    }
    return 0;
}

你可能感兴趣的:(acm,数论,acm,数论-欧拉函数)