• Luogu P2568 GCD


    \(\large{题目链接}\)
    \(\\\)
    求:

    \[\sum\limits_{p \in prime}\sum[\gcd(x,y)=p],1 \leqslant \ x,y \ \leqslant n \leqslant 10^{7} \]

    \(\\\)
    当复习一下今天学习的欧拉函数,考虑式子:

    \[\sum\limits_{p \in prime}\ \sum\limits_{i=1}^{n} \ \sum\limits_{j=1}^{n} [\gcd(i,j)=p] \\ \sum\limits_{p \in prime}\sum\limits_{i=1}^{\lfloor\tfrac{n}{p}\rfloor}\sum\limits_{j=1}^{\lfloor\tfrac{n}{p}\rfloor} [\gcd(i,j)=1] \\ \sum\limits_{p \in prime} \left( \sum\limits_{i=1}^{\lfloor\tfrac{n}{p}\rfloor} \left(\sum\limits_{j=1}^{i} [\gcd(i,j)=1] \times 2 \right)- \sum_{k=1}^{\lfloor\tfrac{n}{p}\rfloor}[\gcd(k,k)=1]\right) \]

    因为\(\sum_{k=1}^{i}[\gcd(k,k)]=1\)中只有\([\gcd(1,1)=1]=1\),其余都为0,对结果没有影响,所以我们可以把式子写为:

    \[\sum_{p \in prime} \left( \sum\limits_{i=1}^{\lfloor\tfrac{n}{p}\rfloor} \varphi(i) \times 2 - 1\right) \]

    \(\\\)
    然后我们可以求出\(\varphi(i)\)后求出\(\varphi(i)\)的前缀和,方便枚举\(prime\)时直接查询。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 1e7 + 5;
    typedef long long ll;
    ll n, cnt, vis[N], pri[N], phi[N], sum[N];
    
    ll read() {
    	ll x = 0, f = 1;
    	char c = getchar();
    	while (!isdigit(c)) {
    		if (c == '-') f = -1;
    		c = getchar();
    	}
    	while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
    	return x * f;
    }
    
    inline void varphi() {
    	phi[1] = 1;
    	for (int i = 2; i <= n; ++i) {
    		if (!vis[i]) {
    			vis[i] = i;
    			phi[i] = i - 1;
    			pri[++cnt] = i;
    		}
    		for (int j = 1; j <= cnt && pri[j] * i <= n; ++j) {
    			vis[i * pri[j]] = pri[j];
    			if (i % pri[j] != 0) phi[pri[j] * i] = (pri[j] - 1) * phi[i];
    			else {
    				phi[i * pri[j]] = phi[i] * pri[j];
    				break;
    			}
    		}
    	}
    } 
    
    int main() {
    	n = read();
    	varphi();
    	ll ans = 0;
    	//for (int i = 1; i <= n; ++i) cout << phi[i] << " ";
    	//cout << endl; 
    	//ans = cnt;
    	//phi[1] = 0;
    	for (int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + phi[i];
    	for (int i = 1; i <= cnt; ++i) {
    		ans += (sum[n / pri[i]] << 1) - 1;
    	}
    	printf("%lld\n", ans);
    	return 0;
    }
  • 相关阅读:
    一周总结
    [z]OpenGL Wiki
    [Z]OpenCL Data Parallel Primitives Library
    [z]苹果用OpenCL实现的Parallel Prefix Sum
    指定VC中std::sort的比较函数时发生"invalid operator<"错误原因
    [z]FNV哈希算法
    [z]NViDIA用OpenCL实现的很多基础并行算法
    [z]一个基于CUDA的基础并行算法库
    [z]一个讲解很多OpenGL中基本概念的网站
    [Z]Marching Cubes的实现
  • 原文地址:https://www.cnblogs.com/Miraclys/p/16703904.html
Copyright © 2020-2023  润新知