zoukankan      html  css  js  c++  java
  • P2568 GCD

    题意描述:

    洛谷

    给你一个 \(n\)\(\displaystyle\sum_{i=1}^{n}\sum_{j=1}^{n} [gcd(i,j)为质数]\)

    数据范围:\(n\leq 10^7\)

    sloution

    首先我们很容易想出来怎么打暴力,我们可以对于每个 \(i\)\(j\) 都求一遍他们的 \(gcd\) 最后累计一下 \(gcd\) 为质数的就完成了。

    可是这样得神仙时间复杂度 为 \(O(n^2)\), 对于这道题,我们肯定会 TLE。

    我们就只能苦逼的想正解QAQ

    然后就开始我们的推柿子时间QAQ

    我们考虑这个柿子: \(gcd(x,y) = p\)

    那么这个柿子可以写成 \(gcd(x' * p , y' * p) = p\)

    提出 \(p\) 来就可以变成 \(gcd(x',y') = 1; x' = x / p ,y' = y / p\);

    我们有一个推论就是:

    \(\displaystyle\sum_{i=1}^{n}\sum_{j=1}^{n} [gcd(i,j) = 1]\) 不就相当于 \(\displaystyle 2 \times \sum_{i=1}^{N} \varphi(i) -1\)

    证明:
    因为 \(gcd(i,j) = gcd(j,i)\), 所以 \(\displaystyle\sum_{i=1}^{n}\sum_{j=1}^{n} [gcd(i,j) == 1] = (2\times \sum_{i=1}^{n}\sum_{j=1}^{i} [gcd(i,j) == 1])-1\), (\(-1\) 是因为 \(i = j = 1\) 的时候算了两次)。
    \(\displaystyle\sum_{j=1}^{i} [gcd(i,j) == 1]\) 等价于 \(1-i\) 内与 \(i\) 互质的个数,也就是 \(\varphi(i)\)
    那么我们的式子可以写成: \(2\times \displaystyle\sum_{i=1}^{n} \varphi(i) - 1\)

    因此对于每个 \(p\),他的贡献就是 \(\displaystyle 2\times \sum_{i=1}^{N\over p} \varphi(i) -1\).

    那么有多少个这样的 \(p\) 呢???

    其实 \(p\) 就是 \(N\) 以内的质数,对于每个 \(p\),求一下他的贡献,在相加,不就可以轻松AC了吗QAQ。。。

    那么最后的总柿子就是

    \(\displaystyle\sum_{p} (2\times \sum_{i=1}^{N\over p} \varphi(i))-1 ( p 是1~n的质数)\)

    优化: 我们再求 \(p\) 的贡献时,不必要一个个的去求欧拉函数的值,我们可以考虑维护
    一下前缀和。这样就会减少不少时间了...

    最后附上我的代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int N = 1e7+10;
    long long n,ans = 0,cnt;
    long long prime[N] ,phi[N], tot[N];
    bool check[N];
    void calc(int n){//边进行欧拉筛,边求欧拉函数
         memset(check,-1,sizeof(check));
         phi[1] = 1;
         for(int i = 2; i <= n; i++){
         	if(check[i]){
         		phi[i] = i-1;
         		prime[++cnt] = i;
         	}
         	for(int  j = 1; j <= cnt; j++){
         		if(i * prime[j] > n) break;
         		check[i*prime[j]] = 0;
         		if(i % prime[j] == 0){
         			phi[i*prime[j]] = phi[i] * prime[j];
         			break;
         		}
         		else{/积性函数性质
         			phi[i*prime[j]] = phi[i] * phi[prime[j]];
         		}
         	}
         }
         for(int i = 1; i <= n; i++) tot[i] = tot[i-1] + phi[i];//前缀和
    }
    int main(){
        scanf("%d",&n);
        calc(n);
        for(int i = 1; i <= cnt; i++){//枚举每个p
        	ans += 2 * tot[n/prime[i]] - 1;//求p的贡献
        }
        printf("%d\n",ans)
        return 0;
    }
    
  • 相关阅读:
    ZOJ 1002 Fire Net (火力网)
    UVa OJ 117 The Postal Worker Rings Once (让邮差只走一圈)
    UVa OJ 118 Mutant Flatworld Explorers (变体扁平世界探索器)
    UVa OJ 103 Stacking Boxes (嵌套盒子)
    UVa OJ 110 MetaLoopless Sorts (无循环元排序)
    第一次遇到使用NSNull的场景
    NSURL使用浅析
    从CNTV下载《小小智慧树》
    NSDictionary and NSMutableDictionary
    Category in static library
  • 原文地址:https://www.cnblogs.com/genshy/p/13300950.html
Copyright © 2011-2022 走看看