于神之怒 (今天第一个没看题解的题...)
确实今天第一个没看题解的题...
而且一开始打的是log筛,cogs上过了,大视野过不了
然后打线性筛,为了不当孙子,坚持不看题解,竟然蒙对了
$$ ans=\sum_{i=1}^n\sum_{j=1}^m gcd(i,j) $$
$$ ans=\sum_{i=1}^{min(n,m)}i^k\sum_{i|d}\mu(\frac{d}{i})\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor $$
$$ ans=\sum_{d=1}^{min(n,m)}\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor\sum_{i|d}\mu(\frac{i}{d})d^k $$
并不知道狄利克雷卷积是什么东西
然后就打了log筛
线性筛:
1.i是质数,$F_i=i^k-1$
2.i与prime[j]互质 $F_{i*prime[j]}=F_i*F_{prime[j]}$
3.i与prime[j]不互质 $F_{i*prime[j]}=F_i*prime[j]^k$
因为当d|i,d不包含prime[j]时,$\mu(\frac{i*prime[j]}{d})=0$,无贡献
而当有因数的时候,直接乘上 贡献即可
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; inline int read() { char q=getchar();int ans=0; while(q<'0'||q>'9')q=getchar(); while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();} return ans; } const int mod=1000000007; const int N=5000006; ll qpow(ll a,int ci) { ll ans=1; while(ci) { if(ci&1) ans=ans*a%mod; a=a*a%mod; ci>>=1; } return ans; } int T,K,n,m; ll mi[N]; int prime[N],cnt; bool he[N]; int mu[N]; ll ji[N]; void chu() { for(int i=0;i<N;++i) mi[i]=qpow(i,K)%mod; mu[1]=1;ji[1]=1; for(int i=2;i<N;++i) { if(!he[i]) { prime[++cnt]=i; mu[i]=-1; ji[i]=mi[i]-1; } for(int j=1;j<=cnt&&prime[j]*i<N;++j) { he[i*prime[j]]=1; if(i%prime[j]==0) { mu[i*prime[j]]=0; ji[i*prime[j]]=mi[prime[j]]*ji[i]%mod; break; } mu[i*prime[j]]=-mu[i]; ji[i*prime[j]]=ji[i]*ji[prime[j]]%mod; } } for(int i=1;i<N;++i) ji[i]+=ji[i-1],ji[i]%=mod; } ll work() { if(n>m) swap(n,m); ll ans=0; int nx; for(int i=1;i<=n;i=nx+1) { nx=min( n/(n/i),m/(m/i) ); ans+=(ll)(n/i)*(m/i)%mod*(ji[nx]-ji[i-1]+mod)%mod; ans%=mod; } return (ans+mod)%mod; } int main(){ //freopen("bzoj_44074.in","r",stdin); //freopen("bzoj_4407.out","w",stdout); //freopen("out.out","w",stdout); T=read();K=read(); chu(); while(T--) { n=read();m=read(); printf("%lld\n",work()); } }