洛谷 P2568 GCD-提高+/省选−
题目描述
给定正整数 nnn,求 1≤x,y≤n1\le x,y\le n1≤x,y≤n 且 gcd(x,y)\gcd(x,y)gcd(x,y) 为素数的数对 (x,y)(x,y)(x,y) 有多少对。
输入格式
只有一行一个整数,代表 nnn。
输出格式
一行一个整数表示答案。
输入输出样例 #1
输入 #1
4
输出 #1
4
说明/提示
样例输入输出 1 解释
对于样例,满足条件的 (x,y)(x,y)(x,y) 为 (2,2)(2,2)(2,2),(2,4)(2,4)(2,4),(3,3)(3,3)(3,3),(4,2)(4,2)(4,2)。
数据规模与约定
- 对于 100%100\%100% 的数据,保证 1≤n≤1071\le n\le10^71≤n≤107。
来源:bzoj2818。
本题数据为洛谷自造数据,使用 CYaRon 耗时 555 分钟完成数据制作。
solution
- 若 gcd(x,y) = p 则 x,y 均为 p 的倍数,且其余部分互质。
- 1 若 x=p∗px,[1,px]x = p * p_x, [1, p_x]x=p∗px,[1,px] 中和 pxp_xpx 互质的有 ϕ(x)\phi(x)ϕ(x) 个(欧拉函数),即
∑p<=n∑i=1n/p(ϕ(i)∗2−1)\sum_{p<=n}\sum_{i = 1}^{n / p}(\phi(i)*2-1)p<=n∑i=1∑n/p(ϕ(i)∗2−1) - 2 例如 n=4时,p=2,[ϕ(1)+ϕ(2)]∗2−1=3。p=3,ϕ(1)∗2−1=1n = 4时,p = 2 , [\phi(1) + \phi(2)] * 2-1 = 3。p = 3, \phi(1)*2 - 1 = 1n=4时,p=2,[ϕ(1)+ϕ(2)]∗2−1=3。p=3,ϕ(1)∗2−1=1
- 1 若 x=p∗px,[1,px]x = p * p_x, [1, p_x]x=p∗px,[1,px] 中和 pxp_xpx 互质的有 ϕ(x)\phi(x)ϕ(x) 个(欧拉函数),即
- 具体:
- 1 筛选出质数 p, 并算出 ϕ(i),i∈[1,n]\phi(i),\,\, i\in[1,n]ϕ(i),i∈[1,n]
- 2 遍历质数,统计个数
代码
#include "cstring"
#include "string"
#include "algorithm"
#include "iostream"
#include "vector"
#include "unordered_set"
#include "unordered_map"
#include "bitset"
#include "queue"
#include "set"using namespace std;/** P2568 GCD* 题目大意:给定正整数 n,求 1≤x,y≤n 且 gcd(x,y) 为素数的数对 (x,y) 有多少对。* 思路: 若 gcd(x,y) = p 则 x,y 均为 p 的倍数,且其余部分互质。* 1 若 x = p * px, [1, px] 中和 px 互质的有 phi(x) 个,即 sum(p, sum(phi(px))*2-1) i=[1,n/p]* 2 例如 n = 4, p = 2 [phi(1) + phi(2)] * 2-1 = 3 p = 3 phi(1)*2 - 1 = 1* 具体:* 1 筛选出质数p, 并算出 phi(i) i=1,n* 2 遍历质数,统计个数**/const int N = 1e7 + 5, M = 2e6, INF = 1e9, MOD = 0;
typedef long long ll;int prime[N], n, k, f[N], np[N];int main() {cin >> n;// 1 筛选出 n 以内所有质数, 和欧拉函数 f[x]f[1] = 1;for (int i = 2; i <= n; i++) {if (!np[i]) prime[++k] = i, f[i] = i - 1;else f[i] = (i / np[i] % np[i] == 0) ? f[i / np[i]] * np[i] : f[i / np[i]] * (np[i] - 1);for (int j = 1; j <= k && prime[j] * i <= n; j++) {np[i * prime[j]] = prime[j];if (i % prime[j] == 0) break;}}ll ans = 0;for (int i = 1; i <= k; i++) {for (int j = 1; j * prime[i] <= n; j++)ans += f[j] * 2;ans--;}cout << ans;return 0;
}