codeforce每日一题
题目链接
题目分数:1600
题目描述
输入 $a, b, k$,范围 $[1,1e6]$,$a≤b$。
请找到最短的 $L$,使得对于任意 $a≤x≤b-L+1$ 都满足:在 $x,x+1,…,x+L-1$ 中至少有$ k$ 个质数。
输出 $L$。如果$L$ 不存在,输出 $-1$。
样例
输入样例1
2 4 2
输出样例1
3
输入样例2
1 4 3
输出样例2
-1
算法1
(二分) $O(n*log(n))$
我们可以二分答案,每次判断的时候从前向后枚举看当前区间是否有至少k个质数。
C++ 代码
// https://www.acwing.com/blog/content/34755/
#include<bits/stdc++.h>
#define rep(i, a, b) for(int i=a;i<=b;i++)
#define per(i, a, b) for(int i=b;i>=a;i--)
#define endl '\n'
#define fi first
#define se second
#define all(a) a.begin(), a.end()
#define pd push_back
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef pair<double, double> PDD;
const int N = 1e6 + 10, M = N * 2, INF = 0x3f3f3f3f, mod = 998244353;
int n, m, k;
int primes[N], cnt;
bool st[N];
inline void init(int n)
{
st[1] = true;
for(int i=2;i<=n;i++)
{
if(!st[i]) primes[cnt++] = i;
for(int j=0;i<=n/primes[j];j++)
{
st[i*primes[j]] = true;
if(i%primes[j]==0) break;
}
}
}
inline void solve()
{
auto check = [&](int mid)
{
int tmp = 0;
for(int i=n;i<=n+mid-1;i++)
if(!st[i]) tmp ++;
for(int i=n,j=n+mid-1;j<=m;i++,j++)
{
if(tmp<k) return false;
if(!st[i]) tmp --;
if(!st[j+1]) tmp ++;
}
return true;
};
cin>>n>>m>>k;
int l = 0, r = m - n + 1;
while(l < r)
{
int mid = l + r >> 1;
if(check(mid)) r = mid;
else l = mid + 1;
}
if(check(r)) cout<<r<<endl;
else cout<<-1<<endl;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
init(N - 1);
solve();
return 0;
}
Java 代码
// https://www.acwing.com/blog/content/34755/
import java.util.*;
public class Main{
public static int N = 1000005, M = N * 2, INF = 0x3f3f3f3f;
public static void solve()
{
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(), m = sc.nextInt(), k = sc.nextInt();
boolean[] st = new boolean[m + 10];
int[] primes = new int[m + 10];
int cnt = 0;
st[1] = true;
for(int i = 2; i <= m; i++)
{
if(!st[i]) primes[cnt++] = i;
for(int j = 0; i <= m / primes[j]; j++)
{
st[i * primes[j]] = true;
if(i % primes[j] == 0) break;
}
}
int tmp = 0;
for(int i = n; i <= m; i++)
if(!st[i]) tmp++;
if(tmp < k) System.out.println(-1);
else{
int l = 0, r = m - n + 1;
while(l < r)
{
int mid = l + r >> 1;
boolean flag = true;
tmp = 0;
for(int i=n;i<=n+mid-1;i++)
if(!st[i]) tmp ++;
for(int i=n,j=n+mid-1;j<=m;i++,j++)
{
if(tmp<k){
flag = false;
break;
}
if(!st[i]) tmp --;
if(!st[j+1]) tmp ++;
}
if(flag) r = mid;
else l = mid + 1;
}
System.out.println(r);
}
}
public static void main(String[] args)
{
solve();
}
}
Python 代码
# https://www.acwing.com/blog/content/34755/
st = [0] * (1000011)
primes = [0] * (1000011)
def init(n:int):
st[1] = True
cnt = 0
for i in range(2, n + 1):
if st[i] == False:
primes[cnt] = i
cnt += 1
j = 0
while i <= n / primes[j]:
st[i * primes[j]] = True
if i % primes[j] == 0:
break
j += 1
def check(mid:int, n:int, m:int, k:int) -> bool:
tmp = 0
for i in range(n, n + mid):
if st[i] == False: tmp += 1
i = n
for j in range(n + mid - 1, m + 1):
if tmp < k: return False
if st[i] == False: tmp -= 1
if st[j+1] == False: tmp += 1
i += 1
return True
def solve():
n, m, k = map(int, input().split())
init(m + 10)
l, r = 0, m - n + 1
while l < r:
mid = l + r >> 1
if check(mid, n, m, k):
r = mid
else:
l = mid + 1
if check(r, n, m, k):
print(r)
else:
print(-1)
def main():
solve()
if __name__ == '__main__':
main()
算法2
(枚举 + 双指针) $O(n)$
我们可以用双指针维护一个区间,保证这个区间内的质数数量恰好等于k个,这样可以是为了保证最后求得的l最小。注意最后当右指针超出区间后要记得更新答案,因为这时答案至少要大于当前的区间。
C++ 代码
// https://www.acwing.com/blog/content/34755/
#include<bits/stdc++.h>
#define rep(i, a, b) for(int i=a;i<=b;i++)
#define per(i, a, b) for(int i=b;i>=a;i--)
#define endl '\n'
#define fi first
#define se second
#define all(a) a.begin(), a.end()
#define pd push_back
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef pair<double, double> PDD;
const int N = 1e6 + 10, M = N * 2, INF = 0x3f3f3f3f, mod = 998244353;
int n, m, k;
int primes[N], cnt;
bool st[N];
inline void init(int n)
{
st[1] = true;
for(int i=2;i<=n;i++)
{
if(!st[i]) primes[cnt++] = i;
for(int j=0;i<=n/primes[j];j++)
{
st[i*primes[j]] = true;
if(i%primes[j]==0) break;
}
}
}
inline void solve()
{
cin>>n>>m>>k;
int tmp = 0;
for(int i=n;i<=m;i++)
if(!st[i]) tmp++;
if(tmp<k) cout<<-1<<endl;
else{
int res = 0, tmp = !st[n];
for(int i=n,j=n+1;;i++){
while(tmp<k && j<=m){
if(!st[j++]) tmp++;
}
if(tmp<k){
res = max(res, j - i + 1);
break;
}
res = max(res, j - i);
if(!st[i]) tmp--;
if(j>m) break;
}
cout<<res<<endl;
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
init(N - 1);
solve();
return 0;
}
Java 代码
// https://www.acwing.com/blog/content/34755/
import java.util.*;
public class Main{
public static int N = 200005, M = N * 2, INF = 0x3f3f3f3f;
public static void solve()
{
Scanner sc = new Scanner(System.in);
int n = sc.nextInt(), m = sc.nextInt(), k = sc.nextInt();
boolean[] st = new boolean[m + 10];
int[] primes = new int[m + 10];
int cnt = 0;
st[1] = true;
for(int i = 2; i <= m; i++)
{
if(!st[i]) primes[cnt++] = i;
for(int j = 0; i <= m / primes[j]; j++)
{
st[i * primes[j]] = true;
if(i % primes[j] == 0) break;
}
}
int tmp = 0;
for(int i = n; i <= m; i++)
if(!st[i]) tmp++;
if(tmp < k) System.out.println(-1);
else{
int res = 0;
if(st[n] == false) tmp = 1;
else tmp = 0;
for(int i=n,j=n+1;;i++){
while(tmp<k && j<=m){
if(!st[j++]) tmp++;
}
if(tmp<k){
res = Math.max(res, j - i + 1);
break;
}
res = Math.max(res, j - i);
if(!st[i]) tmp--;
if(j>m) break;
}
System.out.println(res);
}
}
public static void main(String[] args)
{
solve();
}
}
Python 代码
# https://www.acwing.com/blog/content/34755/
st = [0] * (1000011)
primes = [0] * (1000011)
def init(n:int):
st[1] = True
cnt = 0
for i in range(2, n + 1):
if st[i] == False:
primes[cnt] = i
cnt += 1
j = 0
while i <= n / primes[j]:
st[i * primes[j]] = True
if i % primes[j] == 0:
break
j += 1
def solve():
n, m, k = map(int, input().split())
init(m + 10)
tmp = 0;
for i in range(n, m + 1):
if st[i] == False: tmp += 1
if tmp < k: print(-1)
else:
res, tmp = 0, st[n] == False
j = n + 1
for i in range(n, m + 1):
while tmp<k and j<=m:
if st[j] == False: tmp += 1
j += 1
if tmp < k:
res = max(res, j - i + 1)
break
res = max(res, j - i)
if st[i] == False: tmp -= 1
if j > m: break
print(res)
def main():
solve()
if __name__ == '__main__':
main()