#莫比乌斯反演,整除分块#洛谷 6222 「P6156 简单题」加强版
题目
多组询问,给出\(n,k\)
求
\[\sum_{i=1}^n\sum_{j=1}^n(i+j)^kgcd(i,j)\mu^2(gcd(i,j))
\]
对\(\text{unsigned}\)自然溢出
分析
推式子
\[=\sum_{d=1}^n\mu^2(d)d^{k+1}\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{d}\rfloor}(i+j)^k[gcd(i,j)==1]
\]
\[=\sum_{d=1}^n\mu^2(d)d^{k+1}\sum_{t=1}^{\lfloor\frac{n}{d}\rfloor}\mu(t)t^k\sum_{i=1}^{\lfloor\frac{n}{td}\rfloor}\sum_{j=1}^{\lfloor\frac{n}{td}\rfloor}(i+j)^k
\]
后面这一坨可以预处理出来,记作\(F\)
然后枚举\(D=td\)
那么
\[=\sum_{D=1}^nF(\frac{n}{D})D^k\sum_{d|D}d\mu^2(d)\mu(\frac{D}{d})
\]
后面这一坨是一个积性函数,分类讨论一下就可以了
代码
#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
typedef unsigned uit;
const uit N=20000011; bool v[N];
uit dp[N],f[N],prime[N],Cnt;
inline uit iut(){
rr uit ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(uit ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
inline uit ksm(uit x,uit y){
rr uit ans=1;
for (;y;y>>=1,x=x*x)
if (y&1) ans=ans*x;
return ans;
}
inline void Pro(uit n,uit k){
dp[1]=f[1]=1;
for (rr uit i=2;i<=n;++i){
if (!v[i]) prime[++Cnt]=i,f[i]=ksm(i,k),dp[i]=i-1;
for (rr uit j=1;j<=Cnt&&prime[j]<=n/i;++j){
v[i*prime[j]]=1,f[i*prime[j]]=f[i]*f[prime[j]];
if (i%prime[j]==0){
rr uit t=i/prime[j];
if (t%prime[j]) dp[i*prime[j]]=-prime[j]*dp[t];
break;
}
dp[i*prime[j]]=dp[i]*(prime[j]-1);
}
}
for (rr uit i=2;i<=n;++i) dp[i]=dp[i-1]+dp[i]*f[i];
for (rr uit i=2;i<=n;++i) f[i]+=f[i-1];
for (rr uit i=2;i<=n;++i) f[i]+=f[i-1];
}
inline uit F(uit n){return f[n<<1]-f[n]-f[n];}
signed main(){
rr uit Test=iut(),MX=iut(); Pro(MX<<1,iut());
for (rr uit ans=0,i=1;i<=Test;++i,ans=0){
rr uit n=iut();
for (rr uit l=1,r;l<=n;l=r+1)
r=n/(n/l),ans+=(dp[r]-dp[l-1])*F(n/l);
print(ans),putchar(10);
}
return 0;
}