zoukankan      html  css  js  c++  java
  • HDU-5608(杜教筛)

    HDU-5608(杜教筛)

    题意:(G(n)=n^2−3n+2=sum_{d|n}F(d)),求(sum_1^nF(i))

    反演得到:(F(n)=sum_{d|n}mu(d)G(frac{n}{d}))

    (sum_1^nF(i)=sum_isum_{d|i}mu(d)G(frac{i}{d}))

    (sum_1^nF(i)=sum_{i=1}^{n}G(i)sum_{j=1}^{lfloor frac{n}{i} floor }mu(j))

    问题就是要快速求(G(i))前缀和和(mu(i))前缀和

    第一个是(O(1))求,第二个是杜教筛

    
    const int N=5e6+10,P=1e9+7;
    
    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;
    }
    
    const int Inv6=qpow(6);
    
    int n;
    char notpri[N],w[N];
    int pri[N/4],pc,Sw[N];
    map <int,int> M;
    
    int SumG(int n){ // O(1)求出G函数的前缀和
    	ll ans=1ll*n*(n+1)%P*(2*n+1)%P*Inv6%P;
    	ans=(ans-3ll*n*(n+1)/2%P+2*n)%P;
    	ans=(ans%P+P)%P;
    	return ans;
    }
    
    int Sumw(int n){ // 杜教筛求mobius函数前缀和
    	if(n<N) return Sw[n];
    	if(M.count(n)) return M[n];
    	int ans=1;
    	for(int i=2,j;i<=n;i=j+1) {
    		j=n/(n/i);
    		ans-=(j-i+1)*Sumw(n/i);
    	}
    
    	return M[n]=ans;
    }
    
    int SumF(int n){ // 答案
    	int ans=0;
    	for(int i=1,j;i<=n;i=j+1) {
    		j=n/(n/i);
    		ans=(ans+1ll*(SumG(j)-SumG(i-1))*Sumw(n/i))%P;
    	}
    	ans=(ans%P+P)%P;
    	return ans;
    }
    
    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];
    		}
    	}
    	rep(i,1,N-1) Sw[i]=Sw[i-1]+w[i];
    	rep(kase,1,rd()) printf("%d
    ",SumF(rd()));
    }
    
    
    
    
    
  • 相关阅读:
    scanf与scanf_s的区别
    PAT 1041 考试座位号
    PAT1018 锤子剪刀布
    Cookie
    JSP--原理
    多线程练习题
    Java线程--线程的同步与锁
    有关toString()和println(Object)
    Java Web请求和响应机制
    IO流
  • 原文地址:https://www.cnblogs.com/chasedeath/p/13026879.html
Copyright © 2011-2022 走看看