P2568 GCD()
给定正整数 n,求 1≤x,y≤n 且 gcd(x,y) 为素数的数对 (x,y) 有多少对。
思路:求解这个问题前,1-n的gcd(x,y)为1的数对个数我们大家应该都知道,欧拉函数!,然后遍历相加即可
而这题gcd要为素数,那是不是我们对上面公式的x,y同时乘上一个素数是不是就可以了呢,这就是答案,
这样就得到了一个新的数对(tx,ty),而这个数对的数需要在1-n范围内,所以我们需要判断右边界的范围是否超届.
我们遍历1-n,然后循环乘上每个素数,如果没超届答案就加上该数的欧拉值(与小于它的数互素的个数)*2(因为(2,4),(4,2))
具体可以看代码:
code:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 10001000; const int inf = 0x3f3f3f3f; const ll mod = 100000000; int n; int num[maxn]; vector<int>prime; void oula() { for (int i = 2; i <= n; i++) { num[i] = i; } for (int i = 2; i <= n; i++) { if (num[i]==i) {//没处理过,是素数 prime.push_back(i);//存素数 for (int j = i; j <= n; j += i) { num[j] = num[j] / i * (i - 1); } } } } int main() { //freopen("test.txt", "r", stdin); scanf("%d", &n); oula();//欧拉函数求小于i的互素个数 ll ans = prime.size();//特判,两个素数的公约数也为素数 for (int i = 2; i <= n; i++) { for (int x : prime) { if (x * i <= n) {//如果i乘上素数x没有超届,则满足条件 ans += num[i] * 2; } else { break; } } } cout << ans << endl; return 0; }