【JZOJ4161】于神之怒 莫比乌斯反演
任务
答案mod 1e9+7.
解法
容易写出反演:
同时我们还发现,当
所以我们还可以对
总的时间复杂度就是
另外的Trick:
当我们在对
我们还需预处理出
由于逐个预处理
代码
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#include<string.h>
#define ll long long
using namespace std;
const char* fin="ex4161.in";
const char* fout="ex4161.out";
const ll inf=0x7fffffff;
const ll maxn=5000007,mo=1e9+7;
ll n,m,N,i,j,k,ans,t;
ll mu[maxn],p[maxn],s[maxn];
bool bz[maxn];
ll qpower(ll a,ll b){
ll c=1;
while (b){
if (b&1) c=c*a%mo;
a=a*a%mo;
b>>=1;
}
return c;
}
int main(){
scanf("%d%d%d",&n,&m,&N);
if (n>m) swap(n,m);
mu[1]=1;
s[1]=1;
for (i=2;i<maxn;i++){
if (!bz[i]){
mu[i]=-1;
s[i]=qpower(i,N);
p[++p[0]]=i;
}
for (j=1;j<=p[0];j++){
k=i*p[j];
if (k>=maxn) break;
bz[k]=true;
s[k]=s[i]*s[p[j]]%mo;
if (i%p[j]==0){
mu[k]=0;
break;
}else mu[k]=-mu[i];
}
}
for (i=1;i<maxn;i++){
mu[i]+=mu[i-1];
s[i]=(s[i-1]+s[i])%mo;
}
ll cnt=0;
for (ll T=1;T<=n;){
t=min(n/(n/T),m/(m/T));
ll tmp=0,tmd=n/T,tmb=m/T;
for (i=1;i<=tmd;){
cnt++;
j=min(tmd/(n/(i*T)),tmb/(m/(i*T)));
tmp=(tmp+(tmd/i)*(tmb/i)*(mu[j]-mu[i-1]))%mo;
i=j+1;
}
ans=(ans+tmp*(s[t]-s[T-1]))%mo;
T=t+1;
}
ans=(ans%mo+mo)%mo;
printf("%lld",ans);
return 0;
}
Warning
注意卡常,先预算出