BZOJ4407: 于神之怒加强版
4407: 于神之怒加强版
Time Limit: 80 Sec Memory Limit: 512 MBSubmit: 779 Solved: 368
[Submit][Status][Discuss]
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
思路{
把该式变成枚举gcd
Ans=(min(n,m))∑(i=1) (i^k)*F(i) F(d)=∑(1<=i<=n,,1<=j<=m)(d|gcd(i,j))
套路莫比乌斯反演得F(n)=∑(n|d)(n/d)*(m/d)*μ(d/n)
Ans=(min(n,m))∑(i=1) (i^k)* ∑(i|d)(n/d)*(m/d)*μ(d/i)
套路把(n/d)*(m/d)提前
Ans=(min(n,m)) ∑(D=1) (n/D)*(m/D)*∑(i|D) μ(D/i)*(i^k)
关键就是后面这个东东=∑(i|D) μ(D/i)*(i^k)
设G(D)=∑(i|D) μ(D/i)*(i^k).为狄利克雷卷积形式(然而我不知道有什么卵用)
然后打表发现它是一个积性函数,线性筛就可以了.
}
#include<bits/stdc++.h> #define RG register #define il inline #define db double #define LL long long #define N 5000010 #define mod 1000000007 using namespace std; LL p[N],k,t,n,m;bool vis[N]; LL Q[N],F[N]; LL qp(LL a,LL b){ if(!b)return 1;if(b==1)return a; LL tmp=qp(a,(b>>1)); tmp=(tmp*tmp)%mod; if(b&1)tmp=(tmp*a)%mod; return tmp; } void make(){ F[1]=1; for(LL i=2;i<N;++i){ if(!vis[i])p[++p[0]]=i,Q[i]=qp((LL)i,k),F[i]=(Q[i]-1+mod)%mod; for(int j=1;j<=p[0]&&p[j]*i<N;++j){ vis[p[j]*i]=true; if(i%p[j])F[p[j]*i]=(F[i]*F[p[j]])%mod; else {F[p[j]*i]=(F[i]*Q[p[j]])%mod;break;} } } for(int i=2;i<N;++i)F[i]+=F[i-1],F[i]%=mod; } void work(){ LL Ans(0); for(LL l=1,r;l<=n;l=r+1){ r=min(n/(n/l),m/(m/l)); Ans+=(((F[r]-F[l-1]+mod)%mod)*(((LL)(n/l)*(LL)(m/l))%mod))%mod; if(Ans>=mod)Ans-=mod; }cout<<Ans<<"\n"; } int main(){ scanf("%lld%lld",&t,&k);make(); while(t--){ scanf("%lld%lld",&n,&m); if(n>m)swap(n,m);work(); }return 0; }