题目描述
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 N N, you need to find the number of pairs ( i , j ) (i, j) (i,j), where i g c d ( i , j ) \frac{i}{gcd(i, j)} gcd(i,j)iand j g c d ( i , j ) \frac{j}{gcd(i,j)} gcd(i,j)jare both prime and i , j ≤ N i ,j ≤ N i,j≤N. g c d ( i , j ) gcd(i, j) gcd(i,j) is the greatest common divisor of i i i and j j 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 ( i 1 , j 1 i_1,j_1 i1,j1) and pair ( i 2 , j 2 i_2, j_2 i2,j2) are considered different if i 1 ≠ i 2 i_1 ≠ i_2 i1=i2 or j 1 ≠ j 2 j_1 ≠ j_2 j1=j2.
输入描述:
Input has only one line containing a positive integer N N N.
1 ≤ N ≤ 1 0 7 1 ≤ N ≤ 10^7 1≤N≤107
输出描述:
Output one line containing a non-negative integer indicating the number of diff-prime pairs ( i , j ) (i,j) (i,j) where i , j ≤ N i, j ≤ N i,j≤N
输入
3
输出
2
输入
5
输出
6
解决思路:
提示: 1 ≤ i ≤ N 1 \le i \le N 1≤i≤N, 1 ≤ j ≤ N 1 \le j \le N 1≤j≤N,区间素数个数通过前缀和预处理。
已知:需要求解的是数对 ( i , j ) (i,j) (i,j)的个数,此数对满足 i g c d ( i , j ) \frac{i}{gcd(i, j)} gcd(i,j)i与 j g c d ( i , j ) \frac{j}{gcd(i, j)} gcd(i,j)j都为素数,显然 i i i不等于 j j j。
注意: ( 2 , 3 ) (2,3) (2,3)和 ( 3 , 2 ) (3,2) (3,2)为不同的数对。
求解:如果直接枚举数对,是 n 2 n^2 n2的复杂度, 1 e 7 1e7 1e7的数据肯定是过不去的,所以考虑优化这一过程。
令 g = g c d ( i , j ) g=gcd(i,j) g=gcd(i,j), x = i g x=\frac{i}{g} x=gi, y = j g y=\frac{j}{g} y=gj。
枚举 g g g,可以得到 1 ≤ g ≤ N 1 \le g \le N 1≤g≤N, 1 ≤ x ≤ N g 1\le x \le \frac{N}{g} 1≤x≤gN, 1 ≤ y ≤ N g 1\le y \le \frac{N}{g} 1≤y≤gN。
可以发现,数对 ( x , y ) (x,y) (x,y)满足 x x x与 y y y都是素数且 x x x不等于 y y y。
数对 ( x , y ) (x,y) (x,y)的个数为 [ 1 , N g ] [1,\frac{N}{g}] [1,gN]的素数个数乘以 [ 1 , N g ] [1,\frac{N}{g}] [1,gN]的素数个数减一。
这种计算方法其实是组合数学的乘法原理, x x x的选择是 [ 1 , N g ] [1,\frac{N}{g}] [1,gN]的素数,为了保证 y y y不等于 x x x,所以 y y y的选择要比 x x x的选择少一种,故为 [ 1 , N g ] [1,\frac{N}{g}] [1,gN]的素数个数减一。
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 1e7 + 10;
ll pre[N];
bool vis[N];
int prime[N], cnt;
void init(const int n) {
for (int i = 2; i <= n; i++) {
if (!vis[i]) {
pre[i] = 1;
prime[++cnt] = i;
}
for (int j = 1; j <= cnt && i <= n / prime[j]; j++) {
vis[i * prime[j]] = true;
if (i % prime[j] == 0) break;
}
}
}
int main() {
int n; cin >> n;
init(n);
for (int i = 1; i <= n; i++) pre[i] += pre[i - 1];
ll ans = 0;
for (int g = 1; g <= n; g++) {
ans += pre[n / g] * (pre[n / g] - 1);
}
cout << ans << endl;
return 0;
}