【洛谷P5106】dkw的lcm
数论
题目大意:
给定 $n,k$,求下面式子的值。
题解:
考虑 $\varphi$ 是积性函数,容易想到对不同的质数分别考虑。
考虑质数 $p$,当其贡献为 $\varphi(p^t)$ 时,$i_1,i_2,\dots,i_k$ 中至少有一个数要有 $p^t$ 因子,且不能有 $p^{t+1}$ 因子。
考虑 $f(i)$ 表示最大指数(上面的 $t$)为 $i$ 的方案数,$g(i)$ 表示最大指数小于等于 $i$ 的方案数。
显然有 $f(i)=g(i)-\sum_{j=1}^{i-1}f(j)$.
考虑求 $g(i)$。容易想到,$1\sim n$ 中包含 $p^t$ 因子的数的个数为 $\lfloor\frac{n}{p^t}\rfloor$,那么 $1\sim n$ 中不包含 $p^{t+1}$ 的数的个数为 $n-\lfloor\frac{n}{p^{t+1}}\rfloor$.
所以 $g(i)=(n-\lfloor\frac{n}{p^{i+1}}\rfloor)^k$.
然后这部分的贡献为 $\prod_{t} \varphi(p^t)^{f(t)}$.
由于 $f$ 求的是指数部分,根据欧拉定理,应对 $10^9+6$ 取模而不是 $10^9+7$。
对每个质因子计算贡献即可。
时间复杂度 $O(n\log n)$。
Code:
#include<iostream>
using namespace std;
const int N=1e6+5,md=1e9+7;
typedef long long LL;
int n,k,pri[N/10],tot,ans=1;
bool vis[N];
inline int pow(int a,int b,const int&md){
int ret=1;
for(;b;b>>=1,a=(LL)a*a%md)
if(b&1)ret=(LL)ret*a%md;
return ret;
}
void sieve(int n){
for(int i=2;i<=n;++i){
if(!vis[i])pri[++tot]=i;
for(int j=1;j<=tot&&i*pri[j]<=n;++j){
vis[i*pri[j]]=1;
if(i%pri[j]==0)break;
}
}
}
int main(){
cin>>n>>k;
sieve(n);
for(int i=1;i<=tot;++i){
const int p=pri[i];
int pre=pow(n-n/p,k,md-1);
for(int j=1,x=p;;x*=p,++j){
int f=(pow(n-n/((LL)x*p),k,md-1)-pre+md-1)%(md-1);
(pre+=f)%=md-1;
ans=((LL)ans*pow(x/p*(p-1),f,md))%md;
if(n/p<x)break;
}
}
cout<<ans<<endl;
return 0;
}