4407: 于神之怒加强版
Time Limit: 80 Sec Memory Limit: 512 MBSubmit: 560 Solved: 271
[Submit][Status][Discuss]
Description

Input
Output
Sample Input
3 3
Sample Output
HINT
1<=N,M,K<=5000000,1<=T<=2000
Source
分析:
定义$n<=m$...
$sum _{i=1}^{n}sum _{i=1}^{m} gcd(i,j)^k$
$=sum _{d=1}^{n} d^k sum _{x=1}^{n} mu (x) left lfloor frac{n}{xd} ight floor left lfloor frac{m}{xd} ight floor$
令$y=xd$
$sum _{d=1}^{n} d^k sum _{dmid y} mu (frac{y}{d}) left lfloor frac{n}{y} ight floor left lfloor frac{m}{y} ight floor$
$=sum _{y=1}^{n} left lfloor frac{n}{y} ight floor left lfloor frac{m}{y} ight floor sum _{dmid y} mu( frac{y}{d} ) d^k$
令$f(n)=sum _{dmid n} mu (frac{n}{d}) d^k$,可以通过线性筛线性求出$f(x)$...
因为$f(x)$是一个积性函数,所以有以下转化:
$f(n)=Pi _{i=1}^{t} f(p_i^{x_i})$
$=Pi _{i=1}^{t} sum _{dmid p_i^{x_i}} mu (frac{p_i^{x_i}}{d}) d^k$
因为当一个数含有平方因子的时候$mu (x)=0$,所以可以发现之后下面的两项是有用的...
$=Pi _{i=1}^{t} mu (1) p_i^{x_i} +mu (p_i) p_i^{k(x_i-1)}$
$=Pi _{i=1}^{t} p_i^{kx_i}-p_i^{k(x_i-1)}$
$=Pi _{i=1}^{t} p_i^{k(x_i-1)}(p_i^k-1)$
我们发现,当$p$是一个质数的时候,$f(p)=p^k-1$,所以我们可以得到一下等式:
$f[x*p]=f[x]f[p]$ --- $x$%$p eq 0$
$f[x*p]=f[x]*p^k$ --- $x$%$p = 0$
就可以愉快地分块计算了...
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
//by NeighThorn
using namespace std;
const int maxn=5000000+5,mod=1e9+7;
int n,m,k,ans,cas,cnt,f[maxn],g[maxn],pri[maxn],vis[maxn];
inline int power(int x,int y){
int res=1;
while(y){
if(y&1)
res=1LL*res*x%mod;
x=1LL*x*x%mod,y>>=1;
}
return res;
}
signed main(void){
scanf("%d%d",&cas,&k);g[1]=1;
for(int i=2;i<=5000000;i++){
if(!vis[i])
pri[++cnt]=i,vis[i]=1,f[i]=power(i,k),g[i]=f[i]-1;
for(int j=1;j<=cnt&&1LL*i*pri[j]<=5000000;j++){
vis[i*pri[j]]=1;
if(i%pri[j]==0){
g[i*pri[j]]=1LL*g[i]*f[pri[j]]%mod;
break;
}
g[i*pri[j]]=1LL*g[i]*g[pri[j]]%mod;
}
}
for(int i=2;i<=5000000;i++)
g[i]=(g[i-1]+g[i])%mod;
while(cas--){
scanf("%d%d",&n,&m);ans=0;
if(n>m) swap(n,m);
for(int i=1,r;i<=n;i=r+1){
r=min(n/(n/i),m/(m/i));
ans=(ans+1LL*(n/i)*(m/i)%mod*((g[r]-g[i-1]+mod)%mod)%mod)%mod;
}
printf("%d
",ans);
}
return 0;
}
By NeighThorn