牛客 Diff-prime Pairs (数论+埃氏筛+前缀和)

题目描述

输入描述:
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

首先附上官方题解
Main Idea: Math, Prime Sieve, Prefix Sum

If gcd(i_1, j_1) is not equal to gcd(i_2, j_2), (i_1, j_1) won’t be equal to (i_2, j_2).
The answer will be sum of number of diff-prime pairs whose gcd is g for each g.

Iterate each g, and find two distinct prime p_1, p_2. Then, (g p_1, g p_2) will be an answer if g p_1 <= N and g p_2 <= N. It will be reduced to find the number of prime within (N/g). It can be done by prime sieve and prefix sum.
Since p_1 not equal to p_2, it’s obvious that gcd(g p_1, g p_2)=g
Overall Time complexity: O(N) Overall Space complexity: O(N)

题目分析:这道题目的难度只有一颗星,但是题目给的数据范围达到了1e7之多,暴力的时间复杂度达到了O(n^2),显然是不行的,所以这个题目需要优化+转化,我们不能被题目的表现所迷惑,题目里面有gcd,但是如果去求gcd的话时间复杂度肯定很高,所以这里用了十分巧妙地方法

  • 首先我们用埃氏筛去筛选素数,这是一种十分强大的方法,每次都筛去素数的倍数
  • 然后对其求前缀和,我们把素数的个数求出来,方法后面求素数对
  • 接下来就是题目的核心思想,我们要求一共有所少个素数对,首先素数对中的素数是不能相同的,其次我们枚举每一个公约数,因为素数对的倍数也是符合题目要求,这样只需要求(2,n/g)范围就行,ans += sum[n / g] * (sum[n / g] - 1);减一的操作就是因为用了排列组合数学的思想
  • 遍历每个g,找到两个不同的素数p1,p2,如果g * p1<=n 并且 g * p2<=n,那么(g * p1,g * p2)就是一个符合要求的素数对,那问题就转化成找 n/g 以内的素数的数量,可以通过线性筛出素数再处理前缀和得出。
  • 对于每个含有公因子g的数,都去求一次素数对
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e7 + 10;
int prime[maxn], sum[maxn];
void solve(int x)
{
   
	prime[0] = prime[1] = 1;
	for (int i = 2; i <= x; ++i)
	{
   
		if (!prime[i])
		{
   
			sum[i] = 1;
			for (int j = 2 * i; j <= x; j += i)
				prime[j] = 1;
		}
	}
}
int main()
{
   
	ll n, ans = 0;
	scanf("%lld", &n);
	solve(n);
	for (int i = 1; i <= n; ++i)
		sum[i] += sum[i - 1];
	for (int g = 1; g <= n; ++g)
		ans += sum[n / g] * (sum[n / g] - 1);
	printf("%lld\n", ans);
}
温柔的晚风 傍晚的晚霞 解暑的西瓜 冒泡的可乐 人间的美好多着呢 不要为眼前的黑暗所迷惑 要相信自己值得世间所有美好。
全部评论

相关推荐

正在干活结果人事过来找我,说我被裁了,还说要裁一半,一些没转正的先踢出去…&nbsp;真是牛逼现在的公司,怪不得越做越小。上个月初提交的转正申请,我老大也同意了,我真以为我转正了,结果人事跟我说我老大不知道这些,好吧那你们瞒着呗真是逆天…&nbsp;又要开始找工作了,现在工作哪里这么好找,还有这么多公司喜欢这种操作,坑我们应届生真服了👿
CoderEcho:看你的主页,你好像是有点内向,不怎么说话?我之前实习也是这样的,hr和主管也是用我太内向导致的主管看不到头,工作习惯不好,不适合他们这样的原因把我实习劝退,但是公司肯定有公司的问题,因为去年没一个实习转正的,连社招生都劝退。倒也不是替公司说话,只是一些建议,公司内部裁员肯定是公司的问题,只是积极主动(或者领导眼中积极主动)的人未来一定会有更多机会,刚被劝退的时候基本上秋招已经结束,但是1月份的时候还是上岸啦,并且面试时我说出了我对积极主动的理解也是加分的一点。祝你继续加油往前走,大厂经历+985学历,结果一定不会差的啦
点赞 评论 收藏
分享
01-14 19:01
吉首大学 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务