[2017集訓隊作業自選題#148]Simple Summation Problem

題目大意

定義一個積性函數F。
若p爲質數,F(pd)=pd[d mod p!=0]
求F的前綴和。

做法

G=Fμ ,那麼G也是一個積性函數。
那麼容易得到G(pd)=pd[d mod p!=0]pd1[(d1) mod p!=0]
d=1時G(p)=0。
所以G不爲0,則必須每個質因子指數均>=2。
然後莫比烏斯反演得到F(n)=d|nG(d)
ni=1F(i)=ni=1d|iG(d)
即答案爲nd=1G(d)ni
枚舉出所有質因子指數均>=2的d計算即可。

#include<cstdio> 
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=10000000+10;
int pri[maxn],id[maxn],f[maxn],g[maxn],h[maxn],L[maxn],sta[100][2];
//ll mi[maxn*3],G[maxn*3];
bool bz[maxn];
int i,j,k,l,m,tot,top,cnt;
ll n,N,t,ans;
void prepare(){
    N=floor(sqrt(n));
    fo(i,2,N){
        if (!bz[i]){
            pri[++top]=i;
            id[i]=top;
            f[i]=h[i]=i;
            g[i]=1;
        }
        fo(j,1,top){
            if ((ll)i*pri[j]>N) break;
            bz[i*pri[j]]=1;
            f[i*pri[j]]=pri[j];
            if (i%pri[j]==0){
                g[i*pri[j]]=g[i]+1;
                h[i*pri[j]]=h[i]*pri[j];
                break;
            }
            g[i*pri[j]]=1;
            h[i*pri[j]]=pri[j];
        }
    }
    /*fo(i,1,top){
        L[i]=++tot;
        mi[tot]=t=1;
        G[tot]=0;
        j=0;
        while (t<=(ll)n/pri[i]){
            j++;
            t*=pri[i];
            mi[++tot]=t;
            G[tot]=mi[tot-(j%pri[i]!=0)]-mi[tot-1-((j-1)%pri[i]!=0)];
        }
    }*/
}
/*ll G(int p,int c){
    ll t=mi[L[p]+c-(c%pri[p]!=0)];
    t-=mi[L[p]+c-1-((c-1)%pri[p]!=0)];
    return t;
}*/
void dfs(ll x,ll y,ll z){
    if (!z) return;
    ll p=pri[x];
    if (x==top+1||y>n/p/p){
        ans+=n/y*z;
        return;
    }
    dfs(x+1,y,z);
    ll i=2,j,m=n/y;
    ll t=p,l=1,r;
    m/=t;
    while (m>=p){
        t*=p;
        r=l;
        if ((i-1)%p!=0) r*=p;
        if (i%p==0) r*=p;
        dfs(x+1,y*t,z*(r-l));
        l=r;
        i++;
        m/=p;
    }
}
/*void dg(int x,ll y,ll z,ll m){
    if (!z) return;
    ll t;
    int p=sta[x][0],c=sta[x][1];
    if (x==cnt+1){
        ans+=n/y*z;
        return;
    }
    t=mi[L[p]+2*c];
    dg(x+1,y*t,z*G[L[p]+2*c],m);
    if (m>=pri[p]){
        t*=pri[p];
        dg(x+1,y*t,z*G[L[p]+2*c+1],m/pri[p]);
    }
}
void work(int x){
    cnt=0;
    while (x>1){
        cnt++;
        sta[cnt][0]=id[f[x]];
        sta[cnt][1]=g[x];
        x/=h[x];
    }
    dg(1,1,1,(ll)n/x/x);
}*/
int main(){
    scanf("%lld",&n);
    prepare();
    dfs(1,1,1);
    //fo(i,1,N) work(i);
    printf("%lld\n",ans);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章