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);
}
牛客课后习题题解 文章被收录于专栏

等待蜕变

全部评论

相关推荐

ohs的小木屋:比不少实习待遇高了
点赞 评论 收藏
分享
05-19 19:57
蚌埠学院 Python
2237:Gpa70不算高,建议只写排名,个人技能不在多而在精,缩到8条以内。项目留一个含金量高的,减少间距弄到一页,硕士简历也就一页,本科不要写很多
实习,投递多份简历没人回...
点赞 评论 收藏
分享
05-09 12:23
已编辑
华南理工大学 Java
野猪不是猪🐗:给他装的,双九+有实习的能看的上这种厂我直接吃⑨✌们拿它练练面试愣是给他整出幻觉了
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

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