链接:https://www.nowcoder.com/acm/contest/141/H
来源:牛客网
题目描述
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
示例1
输入
复制
3
输出
复制
2
示例2
输入
复制
5
输出
复制
6
题解:首先要对素数进行打表分析,由于数据过大很容易超限,下面介绍一个接近O(n)的打表方式。
void init() {
p[1]=1,tot=0;
for(int i=2;i<n+1;i++) {
if (!p[i]) p[i]=i,pr[++tot]=i;
for (int j=1;j<=tot&&pr[j]*i<=N;j++) {
p[i*pr[j]]=pr[j];
if (p[i]==pr[j]) break;
}
}
}
出来的结果是,凡是素数p[i]==i。之后要分析出现素数对的关系:列如:n=5时,在3之前有一个素数2,再5之前有2,3,得到的时(1*1+2*1)*2。
代码:
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
// head
const int N=10000000;
int pr[N/5],p[N+100],tot;
int n;
void init() {
p[1]=1;
rep(i,2,N+1) {
if (!p[i]) p[i]=i,pr[++tot]=i;
for (int j=1;j<=tot&&pr[j]*i<=N;j++) {
p[i*pr[j]]=pr[j];
if (p[i]==pr[j]) break;
}
}
}
int main() {
scanf("%d",&n);
init();
int cnt=0; ll ans=0;
for (int i=2;i<=n;i++) if (p[i]==i) {
ans+=(ll)(n/i)*cnt;
cnt++;
}
printf("%lld\n",ans*2);
}