题目链接:https://www.nowcoder.com/acm/contest/141/H
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
![2018牛客网暑期ACM多校训练营(第三场) H - Diff-prime Pairs - [欧拉筛法求素数] 2018牛客网暑期ACM多校训练营(第三场) H - Diff-prime Pairs - [欧拉筛法求素数]](https://image.miaokee.com:8440/aHR0cHM6Ly91cGxvYWRmaWxlcy5ub3djb2Rlci5jb20vZmlsZXMvMjAxODA3MTcvMzA1MzQ1XzE1MzE4MDM5ODY4MzFfZXF1YXRpb24%2FdGV4PSU1Q2ZyYWMlN0JpJTdEJTdCZ2NkKGklMkMlMjBqKSU3RA%3D%3D.jpg?w=700&webp=1)
![2018牛客网暑期ACM多校训练营(第三场) H - Diff-prime Pairs - [欧拉筛法求素数] 2018牛客网暑期ACM多校训练营(第三场) H - Diff-prime Pairs - [欧拉筛法求素数]](https://image.miaokee.com:8440/aHR0cHM6Ly91cGxvYWRmaWxlcy5ub3djb2Rlci5jb20vZmlsZXMvMjAxODA3MTcvMzA1MzQ1XzE1MzE4MDM5ODY4NzJfZXF1YXRpb24%2FdGV4PSU1Q2ZyYWMlN0JqJTdEJTdCZ2NkKGklMkNqKSU3RA%3D%3D.jpg?w=700&webp=1)
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 ≤ 10^7
输出描述:
Output one line containing a non-negative integer indicating the number of diff-prime pairs (i,j) where i, j ≤ N
输入例子:
3
输出例子:
2
-->
输入
3
输出
2
输入
5
输出
6
题意:
给出一个数字 n (1 ≤ n ≤ 1e7),求多少 数对(i, j) 满足 $\frac{i}{{\gcd \left( {i,j} \right)}}$ 和 $\frac{j}{{\gcd \left( {i,j} \right)}}$ 均为质数,且1 ≤ i, j ≤ n。
题解:
筛出[1,n]之间所有的素数,
不难知道,每次取到其中两个素数组成一个素数对(x, y),不妨设 x < y,那么相应的就增加了 $2 \times \left\lfloor {n/y} \right\rfloor $ 个数对;
例如,n=7,取到素数对(2,3),那么 $\left\lfloor {n/3} \right\rfloor = \left\lfloor {7/3} \right\rfloor = 2$,就有 $2 \times 2 = 4$ 个数对:(1*2,1*3) = (2,3)、(3,2)、(2*2,2*3) = (4,6)、(6,4);
对欧拉筛法稍加改造,添加一行代码即可。时间复杂度O(n)。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e7+; int n;
ll ans; bool isPrime[maxn];
int prime[maxn/],cnt;
void screen()//欧拉筛法求素数
{
cnt=;
memset(isPrime,,sizeof(isPrime));
isPrime[]=isPrime[]=;
for(int i=;i<=n;i++)
{
if(isPrime[i])
{
prime[cnt++]=i; ans+=*(n/i)*(cnt-);
//每找到一个素数i,其就可以与前面所有出现过的cnt-1个素数组成cnt-1个素数对,相应的就有2*(n/i)*(cnt-1)个数对 }
for(int j=;j<cnt;j++)
{
if(i*prime[j]>n) break;
isPrime[(i*prime[j])]=;
if(i%prime[j]==) break;
}
}
} int main()
{
scanf("%d",&n);
ans=;
screen();
cout<<ans<<endl;
}