奥斯堕落夫斯基娃的炸鸡(埃式筛 + 尺取)

奥斯堕落夫斯基娃的炸鸡

Description

由于疫情的影响,街道上面很多店铺都关门了,奥斯堕落夫斯基娃不能吃到心爱的炸鸡,所以十分难受,经过了漫长的等待,疫情终于有所好转,所有卖炸鸡的店铺都开门了!于是奥斯堕落夫斯基娃打算戴上口罩去炸鸡街买一些炸鸡(这个街道上所有的店铺都在卖炸鸡,并且卖所有店铺的炸鸡的价格都不相同,第一家店的炸鸡价格为222,第二家店的炸鸡价格为333.......第x家店的炸鸡价格为x+1x+1x+1),当他出家门走了一段时间之后发现,虽然所有卖炸鸡的店铺都开门了,但是因为太多人喜欢吃炸鸡了,并且这个地区的人尤其钟爱素数,所以素数价格的炸鸡都被人们买完了,当他们店铺的炸鸡卖完后就关门休业,所以很多人退而求其次,在不是素数的店铺购买炸鸡,神奇的是这些不是素数的店铺最后都只剩下一只炸鸡。突然,奥斯堕落夫斯基娃发现自己出门着急,忘了带手机了,并且自己口袋里面只剩下nnn元钱,奥斯堕落夫斯基娃是一个强迫症患者,他想着一定要把这些钱花完,不管自己能能买多少只炸鸡,他可以从任意一个店铺开始购买炸鸡(只能从第xxx家店到第x+1x+1x+1家店,不能从第x+1x+1x+1家店到第xxx家店),并且不能跳过与当前购买炸鸡的店铺相邻的开着的炸鸡店去后面的炸鸡店购买炸鸡,你能帮奥斯堕落夫斯基娃计算一下他有多少种刚好把钱花完的选择方案吗?

Input

第一行一个整数TTT,代表TTT组输入T≤50T \leq 50T50

对于接下来的TTT行,输入一个整数nnn,代表奥斯堕落夫斯基娃口袋里有多少钱。(1≤n≤2e51 \leq n \leq 2e51n2e5)

Output

输出一个整数,代表奥斯堕落夫斯基娃有多少种选择方案。

Sample Input 1

2
2
8

Sample Output 1

0
1

Hint

在第七个店铺购买炸鸡的价格为8,所以只购买一只价格为8的炸鸡是一种选择方案,找不到其他的方案使得购买炸鸡的价格总和是8.

Source

bigzong

思路

这一题先用埃式筛 筛选处素数,那么没有被晒出来的就是和数(注意在这一题中 和数1 不能被算进去,第一家炸鸡店的价格才为2),剩下的用尺取维护一下连续区间和 就行了

  • 优化:这一题我们可以对 埃式筛进行优化,定理:如果当前所求的素数i的平方 大于 要求序列的最后一个值,那么这个时候这个序列内的所有数就已经全是素数了,不用再往下循环了break。

题解


#include<iostream>
using namespace std;

const int Len = 2e5 + 100;
int ar[Len];
int br[Len];
int cnt = 0;

void Shai()
{
    for(int i = 2; i < Len; i ++)
        ar[i] = 1;

    for(int i = 2; i < Len; i ++)
    {
      	if(i * i > Len) break;
        if(ar[i])             //这里的 i <= Len/i 是为了减少不必要的循环
        {
            for(int j = i * i; j < Len; j += i)
                ar[j] = 0;
        }
    }
    for(int i = 2; i < Len; i ++)           //这里 i 要从2 开始, 因为第一家炸鸡的 价格为 1 + 1 = 2
    {
        if(!ar[i])
            br[++ cnt] = i;
    }
}


void init()
{
    cnt = 0;
    Shai();
}


int main()
{
    //freopen("A.txt","r",stdin);
    init();
    int t;
    scanf("%d", &t);
    while(t --)
    {
        int n;
        scanf("%d", &n);
        int l = 0, r = 0;
        int sum = 0;
        for(int i = 1; i <= cnt; i ++)
        {
            sum += br[i];
            if(sum >= n)
            {
                r = i;
                break;
            }
        }
        int ans = 0;
        while(true)
        {
            while(sum >= n)
            {
                if(sum == n) ans ++;
                l ++;
                sum -= br[l];
            }

            if(r == cnt) break;

            while(r < cnt && sum < n)
            {
                r ++;
                sum += br[r];
            }

            if(br[r] > n) break;
        }

        printf("%d\n", ans);
    }

    return 0;   
}

发布了149 篇原创文章 · 获赞 228 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_34261446/article/details/105155917