zoukankan      html  css  js  c++  java
  • [51Nod

    题面

    (sum_{i=1}^nsum_{j=1}^nvarphileft(gcd(varphi(i),varphi(j)) ight))
    (nle 2e6)

    题解

    先初步推一推柿子。

    [Ans=sum_{d=1}^nvarphi(d)sum_{i=1}^nsum_{j=1}^n[gcd(varphi(i),varphi(j))==d]$$用$s(k)$表示$n$以内$varphi(i)=k$的正整数$i$的个数。则 $$Ans=sum_{d=1}^nvarphi(d)sum_{i=1}^nsum_{j=1}^ns(i)cdot s(j)cdot[gcd(i,j)==d]\=sum_{d=1}^nvarphi(d)sum_{i=1}^{lfloorfrac nd floor}sum_{j=1}^{lfloorfrac nd floor}s(id)cdot s(jd)cdot[gcd(i,j)==1]$$令$g(d)=sum_{i=1}^{lfloorfrac nd floor}sum_{j=1}^{lfloorfrac nd floor}s(id)cdot s(jd)cdot[gcd(i,j)==1]$,发现不好求。 再令$f(d)=sum_{i=1}^{lfloorfrac nd floor}sum_{j=1}^{lfloorfrac nd floor}s(id)cdot s(jd)$,有: $$f(d)=sum_{k=1}^{lfloorfrac nd floor}g(kd)$$反演后得: $$g(d)=sum_{k=1}^{lfloorfrac nd floor}mu(k)f(kd)\ herefore Ans=sum_{i=1}^nvarphi(n)g(lfloorfrac nd floor)=sum_{d=1}^nvarphi(d)sum_{i=1}mu(i)f(id)]

    那么预处理出来(f),就能求(g)了。直接按照式子(O(nlog n))求。就完事了。

    (O(Tnlog n)),有点慢还是能过。还有个小优化可以把(varphi)(mu)枚举顺序交换一下,那么对于(mu=0)的时候就不用算(也优化不了多少)。

    CODE

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N = 2000005;
    int n, cnt, p[N], phi[N], s[N], mu[N];
    bool vis[N];
    LL f[N];
    
    void init(int N) {
    	phi[1] = mu[1] = 1;
    	for(int i = 2; i <= N; ++i) {
    		if(!vis[i]) p[++cnt] = i, phi[i] = i-1, mu[i] = -1;
    		for(int j = 1, k; j <= cnt && i * p[j] <= N; ++j) {
    			vis[k = i * p[j]] = 1;
    			if(i % p[j] == 0) {
    				mu[k] = 0;
    				phi[k] = phi[i] * p[j];
    				break;
    			}
    			mu[k] = -mu[i];
    			phi[k] = phi[i] * (p[j]-1);
    		}
    	}
    }
    
    int main () {
    	init(2000000); int T, n;
    	scanf("%d", &T);
    	while(T--) {
    		scanf("%d", &n);
    		for(int i = 1; i <= n; ++i) ++s[phi[i]];
    		for(int i = 1; i <= n; ++i) {
    			f[i] = 0;
    			for(int j = i; j <= n; j += i)
    				f[i] += s[j];
    			f[i] = f[i] * f[i];
    		}
    		LL ans = 0;
    		for(int i = 1; i <= n; ++i) if(mu[i]) {
    			LL sum = 0;
    			for(int d = 1; i*d <= n; ++d)
    				sum += phi[d] * f[i*d];
    			ans += sum * mu[i];
    		}
    		printf("%lld
    ", ans);
    		for(int i = 1; i <= n; ++i) --s[phi[i]];
    	}
    }
    
    
  • 相关阅读:
    显示内容和隐藏v-show(以及图标的动态展示)
    主表查询子表
    怎么在pda安装apk
    java学习第40天2020/8/14
    Java学习第39天2020/8/13
    java学习第38天2020/8/12
    java学习第37天2020/8/11
    rz
    git tag
    audio vedio 播放
  • 原文地址:https://www.cnblogs.com/Orz-IE/p/12191787.html
Copyright © 2011-2022 走看看