【题解】sdoj3760线性筛(2018-08-16集训T2)线性筛+埃拉托色尼筛法

25 篇文章 0 订阅
23 篇文章 0 订阅

题目链接

题目描述

XX 摆出了一个难题来考验 YYY。 众所周知,线性筛的一种伪代码如下
输入一个整数 n
申请一个布尔数组 b,初始值全为假
申请一个质数列表 c,初始为空
令 i 从 2 到 n
如果 b[i]为假,那么 c 在尾部增加 i 这个元素
令 j 从头至尾遍历 c 的元素
使 b[i*j]为真
如果 i 为 j 的倍数,那么跳出这层循环
缩进表示语句之间的关系,缩进多的语句嵌套在缩进少的语句中。
但是 XXX 将线性筛的伪代码变成了这样:
输入一个整数 n
申请一个整型数组 b,初始值全为 0
申请一个质数列表 c,初始为空
令 i 从 2 到 n
如果 b[i]为 0,那么 c 在尾部增加 i 这个元素
令 j 从头至尾遍历 c 的元素
使 b[i*j]为 j
如果 i 为 j 的倍数,那么跳出这层循环
现在 XXX 给定整数 k 和 n, YYY 需要回答两个问题:
1:对于未经 XXX 修改的伪代码,输入整数为 n,执行之后,布尔数组 b 中下标在
[k,n]的值为真的个数。
2:对于 XXX 修改后的伪代码,输入整数为 n,执行之后,整型数组 b 中下标在[k,n]
的值的和。
YYY 冷静地思考了一会儿,发现自己并没有什么想法,转而向你求助。你能一眼秒
了此题,加入嘲讽 XXX 的行列吗?

输入

输入文件共一行,两个用空格隔开的正整数 k,n

输出

输出文件共一行,两个用空格隔开的整数。第一个整数为第一个问题的答案,第二
个整数为第二个问题的答案对 998244353 取模的结果

样例输入 1

5 10

样例输出 1

4 9

样例 1 解释

第一个问题的答案 4 为: b[6],b[8],b[9],b[10]为真
第二个问题的答案 9 为: b[6]=b[8]=b[10]=2,b[9]=3

样例输入 2

24788 87347

样例输出 2

56820 605038

数据规模

这里写图片描述


一看这题,诶以前写过类似的,结果所有地方都是long long,除了最前面的int n,k(我也不知道为啥我写int,可能顺手就打了)然后……100->10
引以为戒

#include<cstdio>
#include<cstring>
typedef long long ll;
ll k,n;
const int N=10000000;
const int mod=998244353;
int iscomp[N+10];
int prime[N+10],p;
void primetable()
{
    for(int i=2;i<=N;i++)
    {
        if(!iscomp[i])prime[p++]=i;
        for(int j=0;j<p&&i*prime[j]<=N;j++)
        {
            iscomp[i*prime[j]]=prime[j];
            if(i%prime[j]==0)break;
        }
    }
}
int b[N+10];
int main()
{
    //freopen("linear.in","r",stdin);
    //freopen("linear.out","w",stdout);
    //freopen("in.txt","r",stdin);
    primetable();
    scanf("%lld%lld",&k,&n);
    for(ll i=0;i<p;i++)
    {
        if(prime[i]>n)break;
        ll l=(k-1)/prime[i]+1,r=n/prime[i];
        for(ll j=l;j<=r;j++)
            if(j>1)
            {
                if(prime[i]*j-k<0)continue;
                if(b[prime[i]*j-k]>0)continue;
                b[prime[i]*j-k]=prime[i];
            }
    }
    ll cnt=0,ans=0;
    for(ll i=0;i<=n-k;i++)
    {
        if(!b[i])continue;
        cnt++,ans=(ans+b[i])%mod;
    }
    printf("%lld %lld\n",cnt,ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值