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