HDU 5728 PowMod

11 篇文章 0 订阅
7 篇文章 0 订阅

Description
Declare:
k=mi=1φ(in) mod 1000000007
n is a square-free number.
φ is the Euler’s totient function.
find:
ans=kkkk...kmod p
There are infinite number of k

Solution
比赛时候没推出来。。
下面那个很好搞,和BZOJ3884一样咯,递归搞定
关键是上面
首先令sum(n,m)=mi=1φ(in) mod 1000000007
因为 φ 是积性函数,那么令 p 为n的一个因数
则可以得到sum(n,m)=φ(p)mi=1φ(in/p)+floor(m/p)i=1φ(in)    ...................(1)
关于上面这个式子的推导:
对于那些和 p 互质的i , φ(in)=φ(in/p)φ(p) (积性函数的定义咯)
对于那些和 p 不互质的i φ(in)=φ(in/p)p (欧拉函数的定义,要证明的话可以用剩余系)
p 是个素数,则φ(p)=p1,式 (1) 得证。
于是式 (1) 可以简化为 sum(n,m)=φ(p)sum(n/p,m)+sum(n,floor(m/p))
于是 k 可以在远小于log次调用递归里得到。

当然,关于之前那个 k 的无限次方,题解还有更好的方式(不用每次提项了)
题解给出一个公式

ab mod p=aφ(p)+b mod φ(p)

没有欧拉公式的互素的限制!!!

但是好像有其他限制: b>=φ(p) ,比如这有组反例(2,1,4),当然反例是不满足那个限制的,详情可见知乎
还有证明
然后在这道题里 kkkk...k 是无限大的,所以可以衣食无忧的用哪个公式。
总之有了这个公式后那个BZOJ3884变成了递归入门题PoPoQQQ大爷,我绝无冒犯您的意思。。
数论还是很(ao)有(miao)意(chong)思(chong)的

Code

#include<iostream>
#include<string.h>
#include<algorithm>
#include<stdio.h>
using namespace std;
const int M=1e7+5;
const int P=1e9+7;
bool mark[M];
int prime[M],phi[M],sum[M],t;
inline int Mod(int b){return b>=P?b-P:b;}
inline void pret(){
    phi[1]=1;
    for(int i=2;i<M;++i){
        if(!mark[i])prime[t++]=i,phi[i]=i-1;
        for(int j=0;j<t&&1ll*prime[j]*i<M;++j){
            mark[i*prime[j]]=1;
            if(i%prime[j]==0){
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            phi[prime[j]*i]=phi[i]*(prime[j]-1);
        }
    }
    for(int i=1;i<M;++i)
        sum[i]=Mod(sum[i-1]+phi[i]);
}
inline int work(int n,int m){
    if(n==1)return sum[m];
    if(m==1)return phi[n];
    if(m<1)return 0;
    for(int i=0;prime[i]*prime[i]<=n;++i){
        if(n%prime[i]==0)
            return Mod(1ll*phi[prime[i]]*work(n/prime[i],m)%P+work(n,m/prime[i]));
    }
    return Mod(1ll*phi[n]*work(1,m)%P+work(n,m/n));
}
inline int Mod_Pow(int x,int a,int mod){
    int res=1;
    for(int i=0;(1ll<<i)<=a;++i){
        if(a&1<<i)res=1ll*res*x%mod;
        x=1ll*x*x%mod;
    }
    return res;
}
int n,m,p,k;
inline int gao(int mod){
    if(mod==1)return 0;
    int s=gao(phi[mod]);
    return Mod_Pow(k,s+phi[mod],mod);
}
int main(){
    for(pret();cin>>n>>m>>p;){
        k=work(n,m);
        cout<<gao(p)<<endl;
    }
    return 0;
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值