• 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;
    }
  • 相关阅读:
    7.13dfs例题:部分和
    7.12dfs例题:数独游戏
    1.2题解:如何找数组中唯一成对的那个数(位运算)
    左程云Java算法(1)
    SQL基本语句增删改查
    Python spyder Ipython console 连接失败问题
    VBA——Msgbox
    python 字符串
    Scrapy-selectors总结
    文字单行居中,多行居左/居右
  • 原文地址:https://www.cnblogs.com/Miraclys/p/16703904.html
Copyright © 2020-2023  润新知