[HDU - 6833] A Very Easy Math Problem (莫比乌斯反演)
与(gcd)有关的问题,很容易想到莫比乌斯反演
设(G(a,n)=(sum_{i=1}^{lfloor frac{n}{a} floor } (ai)^k)^x)
(Ans=sum_{g=1}^{n} gcdot f(g)cdot sum _{d=1}^{lfloorfrac{n}{g} floor} mu(d) G(gd,n))
对于单组询问,显然可以(O(nln n))求解
考虑优化
可以在(O(nln n))的时间内,对于每个(i),求出(F(i)=sum_{d|i}mu(d)cdot frac{i}{d} f(frac{i}{d}))
对于(G(a,n))的求解,参数分离后发现 (G(a,n)=a^{kx}(sum_{i=1}^{lfloor frac{n}{a} floor } i^k)^x)
可以预处理出(S(n)=sum_{i=1}^n i^{kx}cdot F(i))前缀和以及(A(n)=(sum_{i=1}^{n}i^k)^x),对于每个$lfloor frac{n}{a} floor $考虑即可
数论分段的复杂度为单组查询(O(sqrt n))
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
char IO;
template <class T=int> T rd(){
T s=0; int f=0;
while(!isdigit(IO=getchar())) if(IO=='-') f=1;
do s=(s<<1)+(s<<3)+(IO^'0');
while(isdigit(IO=getchar()));
return f?-s:s;
}
const int N=2e5+10,P=1e9+7;
int T,n,k,x;
int mk[N],notpri[N],pri[N],pc,w[N];
ll qpow(ll x,ll k=P-2) {
ll res=1;
for(;k;k>>=1,x=x*x%P) if(k&1) res=res*x%P;
return res;
}
int s[N],F[N],S[N],A[N];
int main(){
w[1]=1;
rep(i,2,N-1) {
if(!notpri[i]) pri[++pc]=i,w[i]=-1;
for(int j=1;j<=pc && 1ll*i*pri[j]<N;++j) {
notpri[i*pri[j]]=1;
if(i%pri[j]==0) {
w[i*pri[j]]=0;
break;
}
w[i*pri[j]]=-w[i];
}
}
for(int i=2;i*i<N;++i) for(int j=i*i;j<N;j+=i*i) mk[j]=1;
rep(i,1,N-1) if(!mk[i]) rep(j,1,(N-1)/i) F[i*j]=(F[i*j]+i*w[j]+P)%P;
T=rd(),k=rd(),x=rd();
rep(i,1,N-1) S[i]=(S[i-1]+F[i]*qpow(i,1ll*k*x))%P;
rep(i,1,N-1) A[i]=(A[i-1]+qpow(i,k))%P;
rep(i,1,N-1) A[i]=qpow(A[i],x);
rep(kase,1,T) {
n=rd();
ll ans=0;
for(int i=1,j;i<=n;i=j+1) {
j=n/(n/i);
ans=(ans+1ll*(S[j]-S[i-1])*A[n/i])%P;
}
ans=(ans%P+P)%P;
printf("%lld
",ans);
}
}