[HDU

[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);
    }
}

原文地址:https://www.cnblogs.com/chasedeath/p/13458900.html