P2568 GCD()

传送门

给定正整数 n,求 1x,yn 且 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;
}

 

posted @ 2021-05-25 10:04  cono奇犽哒  阅读(97)  评论(0)    收藏  举报