Description
给下N,M,K.求
Input
输入有多组数据,输入数据的第一行两个正整数T,K,代表有T组数据,K的意义如上所示,下面第二行到第T+1行,每行为两个正整数N,M,其意义如上式所示。
Output
如题
Sample Input
1 2
3 3
3 3
Sample Output
20
HINT
1<=N,M,K<=5000000,1<=T<=2000
$sum_{d=1}^nd^ksum_{i=1}^nsum_{j=1}^m[gcd(i,j)==d]$
$sum_{d=1}^nd^ksum_{i=1}^{n/d}sum_{j=1}^{m/d}[gcd(i,j)==1]$
$sum_{d=1}^nd^ksum_{i=1}^{n/d}mu(i)[frac{n/d}{i}][frac{m/d}{i}]$
$sum_{d=1}^nd^ksum_{i=1}^{n/d}mu(i)[frac{n}{id}][frac{m}{id}]$
令$T=id$
$sum_{d=1}^nd^ksum_{i=1}^{n/d}mu(i)[frac{n}{T}][frac{m}{T}]$
$f(T)=sum_{d|T}d^kmu(frac{T}{d})$
这是一个狄利克雷卷积,一定是积性函数
所以可以用线性筛法求出,不必要用枚举倍数的nlogn的方FA♂
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 typedef long long lol; 8 const int N=5000000; 9 int Mod=1e9+7; 10 int sum[N+5],s[N+5],prime[N+5],tot,k,n,m,ans; 11 bool vis[N+5]; 12 int qpow(int x,int y) 13 { 14 int res=1; 15 while (y) 16 { 17 if (y&1) res=1ll*res*x%Mod; 18 x=1ll*x*x%Mod; 19 y>>=1; 20 } 21 return res; 22 } 23 void pre() 24 {int i,j; 25 sum[1]=1; 26 for (i=2;i<=N;i++) 27 { 28 if (vis[i]==0) 29 { 30 prime[++tot]=i; 31 s[tot]=qpow(i,k); 32 sum[i]=s[tot]-1; 33 } 34 for (j=1;j<=tot;j++) 35 { 36 if (1ll*i*prime[j]>N) break; 37 vis[i*prime[j]]=1; 38 if (i%prime[j]==0) 39 { 40 sum[i*prime[j]]=1ll*sum[i]*s[j]%Mod; 41 break; 42 } 43 else sum[i*prime[j]]=1ll*sum[i]*sum[prime[j]]%Mod; 44 } 45 } 46 for (i=1;i<=N;i++) 47 sum[i]=(sum[i]+sum[i-1])%Mod; 48 } 49 int main() 50 {int T,i,pos; 51 cin>>T>>k; 52 pre(); 53 while (T--) 54 { 55 scanf("%d%d",&n,&m); 56 if (n>m) swap(n,m); 57 ans=0; 58 for (i=1;i<=n;i=pos+1) 59 { 60 pos=min(n/(n/i),m/(m/i)); 61 ans+=1ll*(sum[pos]-sum[i-1]+Mod)%Mod*(n/i)%Mod*(m/i)%Mod; 62 ans%=Mod; 63 } 64 printf("%d ",ans); 65 } 66 }