牛客——Diff-prime Pairs(数论,组合数学)

本文介绍了一种优化算法,用于解决Eddy遇到的diff-primePairs问题,即在给定范围内找出同时拥有两个素数因数且不重复的数对个数。利用前缀素数计数和组合数学原理,降低了复杂度,使得在大范围数据下求解变得高效。
摘要由CSDN通过智能技术生成

Diff-prime Pairs


题目描述

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,jN. 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 1N107

输出描述:

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,jN

输入

3

输出

2

输入

5

输出

6

解决思路

提示 1 ≤ i ≤ N 1 \le i \le N 1iN 1 ≤ j ≤ N 1 \le j \le N 1jN,区间素数个数通过前缀和预处理。
已知:需要求解的是数对 ( 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 1gN 1 ≤ x ≤ N g 1\le x \le \frac{N}{g} 1xgN 1 ≤ y ≤ N g 1\le y \le \frac{N}{g} 1ygN
可以发现,数对 ( 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;
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值