Diff-prime Pairs

H、Diff-prime Pairs

https://ac.nowcoder.com/acm/problem/17247

数论+埃氏筛+前缀和

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

1.首先我们用埃氏筛去筛选素数,这是一种十分强大的方法,每次都筛去素数的倍数
2.然后对其求前缀和,我们把素数的个数求出来,方法后面求素数对
3.接下来就是题目的核心思想,我们要求一共有所少个素数对,首先素数对中的素数是不能相同的,其次我们枚举每一个公约数,因为素数对的倍数也是符合题目要求,这样只需要求(2,n/g)范围就行,ans += sum[n / g] * (sum[n / g] - 1);减一的操作就是因为用了排列组合数学的思想
4.遍历每个g,找到两个不同的素数p1,p2,如果g * p1<=n 并且 g * p2<=n,那么(g * p1,g * p2)就是一个符合要求的素数对,那问题就转化成找 n/g 以内的素数的数量,可以通过线性筛出素数再处理前缀和得出。
5.对于每个含有公因子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);
}
牛客课后习题题解 文章被收录于专栏

等待蜕变

全部评论

相关推荐

程序员牛肉:主要是因为小厂的资金本来就很吃紧,所以更喜欢有实习经历的同学。来了就能上手。 而大厂因为钱多,实习生一天三四百的就不算事。所以愿意培养你,在面试的时候也就不在乎你有没有实习(除非是同级别大厂的实习。) 按照你的简历来看,同质化太严重了。项目也很烂大街。 要么换项目,要么考研。 你现在选择工作的话,前景不是很好了。
点赞 评论 收藏
分享
每晚夜里独自颤抖:这个在牛客不是老熟人了吗
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务