zoukankan      html  css  js  c++  java
  • P3768 简单的数学题

    https://www.luogu.com.cn/problem/P3768
    推式子+杜教筛+整除分块,感觉往 (varphi) 的方向推比往 (mu) 上推要好

    [egin{aligned}sum_{i=1}^nsum_{j=1}^n ijgcd(i,j) &=sum_{i=1}^nsum_{j=1}^n ijsum_{k|gcd(i,j)} varphi(k)\ &=sum_{k}varphi(k)sum_{k|i}^nsum_{k|j}^nij\ &=sum_{k}k^2varphi(k)sum_{i=1}^{lfloorfrac{n}{k} floor}isum_{j=1}^{lfloorfrac{n}{j} floor}j\ &=sum_{k}k^2varphi(k)left(sum_{i=1}^{lfloorfrac{n}{k} floor}i ight)^2\ end{aligned} ]

    然后这个 (left(sum_{i=1}^{lfloorfrac{n}{k} floor}i ight)^2) 可以整除分块并 (O(1)) 求,外面再套一个 (k^2varphi(k)) 用杜教筛算就行了
    至于怎么杜教筛,设 (f=varphi cdot operatorname{Id}^2,g=operatorname{Id}^2),那么就有 (f*g=sum_{d|n} varphi(d)d^2left(frac{n}{d} ight)^2=n^2sum_{d|n} varphi(d)=n^3)
    再设 (s)(f) 的前缀和,根据杜教筛的套路式子,就有:

    [egin{aligned}f(1)s(n) &=sum_{i=1}^ng(i)s(lfloorfrac{n}{i} floor)-sum_{i=2}^ng(i)s(lfloorfrac{n}{i} floor)\ &=sum_{i=1}^n(f*g)(i)-sum_{i=2}^ng(i)s(lfloorfrac{n}{i} floor)\ end{aligned} ]

    由于 (g(i)) 以及 (sum_{i=1}^n(f*g)(i)) 都是很好求的,所以就能直接杜教筛了

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<map>
    #define reg register
    #define LL_INF (long long)(0x3f3f3f3f3f3f3f3f)
    #define INT_INF (int)(0x3f3f3f3f)
    inline long long read(){
    	register long long x=0;register int y=1;
    	register char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=getchar();}
    	return y?x:-x;
    }
    #define maxn 5000000
    long long n;
    long long mod,inv4,inv6;
    std::map<long long,long long>map;
    int notprime[maxn+6],prime[maxn+6];
    long long phi[maxn+6];
    inline long long power(long long a,long long b){
    	long long ans=1;
    	while(b){
    		if(b&1) ans=ans*a%mod;
    		a=a*a%mod;b>>=1;
    	}
    	return ans;
    }
    inline void pre(int n){
    	phi[1]=1;
    	for(reg int i=2;i<=n;i++){
    		if(!notprime[i]) prime[++prime[0]]=i,phi[i]=i-1;
    		for(reg int x,j=1;i*prime[j]<=n&&j<=prime[0];j++){
    			x=i*prime[j];notprime[x]=1;
    			if(i%prime[j]) phi[x]=phi[i]*(prime[j]-1);
    			else{
    				phi[x]=phi[i]*prime[j];break;
    			}
    		}
    		phi[i]=phi[i]*i%mod*i%mod;
    	}
    	for(reg int i=2;i<=n;i++) phi[i]=(phi[i]+phi[i-1])%mod;
    }
    inline long long S2(long long n){
    	n%=mod;
    	return n*(n+1)%mod*(2*n+1)%mod*inv6%mod;
    }
    inline long long S3(long long n){
    	n%=mod;
    	return n*n%mod*(n+1)%mod*(n+1)%mod*inv4%mod;
    }
    long long get(long long n){
    	if(n<=maxn) return phi[n];
    	if(map.find(n)!=map.end()) return map[n];
    	long long ans=S3(n);
    	for(reg long long l=2,r;l<=n;l=r+1){
    		r=n/(n/l);
    		ans=(ans-get(n/l)*(S2(r)-S2(l-1))%mod+mod)%mod;
    	}
    	map[n]=ans;
    	return ans;
    }
    inline long long work(long long n){
    	long long ans=0;
    	for(reg long long l=1,r;l<=n;l=r+1){
    		r=n/(n/l);
    		ans+=S3(n/l)*(get(r)-get(l-1)+mod)%mod;
    		ans%=mod;
    	}
    	return ans;
    }
    int main(){
    	mod=read();n=read();
    	pre(maxn);
    	inv4=power(4,mod-2);inv6=power(6,mod-2);
    	printf("%lld
    ",work(n));
    	return 0;
    }
    
  • 相关阅读:
    【今日CV 视觉论文速览】 19 Nov 2018
    【numpy求和】numpy.sum()求和
    【今日CV 视觉论文速览】16 Nov 2018
    【今日CV 视觉论文速览】15 Nov 2018
    poj 2454 Jersey Politics 随机化
    poj 3318 Matrix Multiplication 随机化算法
    hdu 3400 Line belt 三分法
    poj 3301 Texas Trip 三分法
    poj 2976 Dropping tests 0/1分数规划
    poj 3440 Coin Toss 概率问题
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/14555842.html
Copyright © 2011-2022 走看看