题目链接:https://www.nowcoder.com/acm/contest/141/H
题目描述
输入描述:
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
输入
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+5; int n; ll ans; bool isPrime[maxn]; int prime[maxn/10],cnt; void screen()//欧拉筛法求素数 { cnt=0; memset(isPrime,1,sizeof(isPrime)); isPrime[0]=isPrime[1]=0; for(int i=2;i<=n;i++) { if(isPrime[i]) { prime[cnt++]=i; ans+=2*(n/i)*(cnt-1); //每找到一个素数i,其就可以与前面所有出现过的cnt-1个素数组成cnt-1个素数对,相应的就有2*(n/i)*(cnt-1)个数对 } for(int j=0;j<cnt;j++) { if(i*prime[j]>n) break; isPrime[(i*prime[j])]=0; if(i%prime[j]==0) break; } } } int main() { scanf("%d",&n); ans=0; screen(); cout<<ans<<endl; }
2018牛客网暑期ACM多校训练营(第三场) H - Diff-prime Pairs - [欧拉筛法求素数]
原文:https://www.cnblogs.com/dilthey/p/9371255.html