NOIP模拟题——dun

【问题描述】
定义两个素数是连续的当且仅当这两个素数之间不存在其他的素数(如 7,11 ,(23,29)。给定N,K,在不超过N的正整数中求能够分解为K个连续的素数的和的最大的那个是多少。
【输入格式】
第一行一个正整数T代表数据组数。
接下来T行每行两个正整数N,K代表一组询问。
【输出格式】
输出共T行,每行一个整数代表答案;如果找不到这样的数,输出−1。
【样例输入】
3
20 2
20 3
20 4
【样例输出】
18
15
17
【样例解释】
 ╭︿︿︿╮
  {/ o o /}
   ( (oo) )
    ︶︶︶
【数据规模与约定】
对于20%的数据,1≤N≤100。
对于40%的数据,T=1。
对于60%的数据,所有的询问的N相等。
对于100%的数据,1≤T<2000,1≤N≤106。

一开始肯定是先预处理出所有小于1e6的质数,筛法O(nloglogn)。

由于是2000组数据,1秒钟要算出,所以考虑二分。

预处理先算出素数的前缀和。每次找的时候二分找结束位置,则和为sum[x]-sum[x-k]。

二分的时候要搞清楚末状态,不然很容易错。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 const int maxn=1e6+5;
 8 int prime[maxn];
 9 int vis[maxn];
10 int q[maxn];
11 long long sumx[maxn];
12 int T;long long k,n;int temp=0;
13 long long read()
14 {
15     char c=getchar();long long an=0;
16     while(c<'0'||c>'9')c=getchar();
17     while(c>='0'&&c<='9')
18     {
19         an=an*10+c-'0';
20         c=getchar();
21     }
22     return an;
23 }
24 void solve2()
25 {
26     scanf("%d",&T);
27     for(int qw=1;qw<=T;qw++)
28     {
29         //memset(q,0,sizeof(q));
30         int temp1=0;
31         n=read();k=read();//scanf("%I64d%d",&n,&k);
32         int left=k,right=temp;
33         while(left<=right)
34         {
35             int mid=(left+right)>>1;
36             if(sumx[mid]-sumx[mid-k]<n)
37             left=mid+1;
38             else right=mid-1;
39         }
40         if(sumx[right+1]-sumx[right-k+1]<=n)right++;
41         if(right==k-1)printf("-1
");
42         else printf("%d
",sumx[right]-sumx[right-k]);
43     }
44     return ;
45 }
46 int main()
47 {
48     freopen("dun.in","r",stdin);
49     freopen("dun.out","w",stdout);
50     memset(vis,false,sizeof(vis));
51     for(long long i=2;i<=1000000;i++)
52     {
53         int qw=int(i);
54         if(vis[qw]==true)continue;
55         else 
56         {
57             prime[++temp]=qw;
58             if(qw*qw>1e6)continue;
59             for(long long j=i;j*i<=1000000;j++)
60             {
61                 if(j*i>1000000)break;
62                 int k=int(j*i);
63                 vis[k]=true;
64             }    
65         }
66     }
67     for(int i=1;i<=temp;i++)
68     {
69         sumx[i]=prime[i];
70         sumx[i]+=sumx[i-1];
71     }
72     solve2();
73 }
原文地址:https://www.cnblogs.com/937337156Zhang/p/6047144.html