(第三场) H Diff-prime Pairs 【数论-素数线性筛法+YY】

题目链接

题目描述 

Eddy has solved lots of problem involving calculating the number of coprime pairs within some range. This problem can be solved with inclusion-exclusion method. Eddy has implemented it lots of times. Someday, when he encounters another coprime pairs problem, he comes up with diff-prime pairs problem. diff-prime pairs problem is that given N, you need to find the number of pairs (i, j), where  and  are both prime and i ,j ≤ N. gcd(i, j) is the greatest common divisor of i and j. Prime is an integer greater than 1 and has only 2 positive divisors.

Eddy tried to solve it with inclusion-exclusion method but failed. Please help Eddy to solve this problem.

Note that pair (i1, j1) and pair (i2, j2) are considered different if i1 ≠ i2 or j1 ≠ j2.

输入描述:

Input has only one line containing a positive integer N.

1 ≤ N ≤ 107

输出描述:

Output one line containing a non-negative integer indicating the number of diff-prime pairs (i,j) where i, j ≤ N

 

case 1

input: 

3

output:

2

case 2

input:

5

output:

6

 

题目大意:求 1~N 内满足 i / gcd(i, j) , j / gcd(i, j) 的有序对 i,j 的个数。

思路:

官方题解:

Main Idea: Math, Prime Sieve, Prefix Sum

If gcd(i_1, j_1) is not equal to gcd(i_2, j_2), (i_1, j_1) won’t be equal to (i_2, j_2).
The answer will be sum of number of diff-prime pairs whose gcd is g for each g.

Iterate each g, and find two distinct prime p_1, p_2. Then, (g p_1, g p_2) will be an answer if g p_1 <= N and g p_2 <= N. It will be reduced to find the number of prime within (N/g). It can be done by prime sieve and prefix sum.
Since p_1 not equal to p_2, it’s obvious that gcd(g p_1, g p_2)=g
Overall Time complexity: O(N) Overall Space complexity: O(N)

 

一开始暴力i, j,结果也很暴力直接超时,剪枝也没办法,O(N^2)肯定不用想了

其实这道题的做法是暴力最大公因数 gcd(i, j), 而不是直接暴力i, j, 因为 (i_1, j_1) 和 (i_2, j_2) 不相同说明他们的公因数也不同。所以我们只需要枚举1~N内的公因数 g 再寻找公因数相同下在区间(2, N/g)素数对组合情况就可以了,可以预处理用埃氏筛法打素数表,至于素数对组合,根据排列组合 sum[N/g]*(sum[N/g]-1), sum为前缀和,可以线性预处理出来。所以整道题的算法都是线性的。

AC code:

///2018年牛客暑假多校训练赛第三场 H
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;

const int MAXN = 1e7+10;

bool is_prime[MAXN];
int num[MAXN];
int N;

void sivev(int N)      ///素数表
{
    int p = 0;
    for(int i = 0; i <= N; i++) is_prime[i] = true;
    is_prime[0] = is_prime[1] = 0;
    for(int i = 2; i <= N; i++)
    {
        if(is_prime[i])
        {
            num[i] = 1;
            for(int j = 2*i; j <= N; j+=i) is_prime[j] = 0;
        }
    }
}

int main()
{
    scanf("%d", &N);
    sivev(N);
    for(int i = 1; i <= N; i++)
        num[i]+=num[i-1];

    long long int ans = 0;
    for(int g = 1; g <= N; g++)
    {
        ans+=num[N/g]*(num[N/g]-1);
    }

    printf("%lld\n", ans);

    return 0;
}

 

posted @ 2018-07-27 15:37  莜莫  阅读(313)  评论(0编辑  收藏  举报