列表

详情


NC21350. 质数与合数

描述

FFF和GGG正在玩一个质数与合数的游戏
一开始有N个石头
FFF和GGG轮流对这堆石头进行操作,FFF每次选择1到K之间的一个数x,并拿走x个石头,拿走之后剩下的石头数量必须是质数
接着GGG进行同样的操作,但是要求拿走之后剩下的石头数量必须是合数
假设双方都足够聪明,第一个不能操作的人输
以为到这里就结束了?
显然,一开始两人之间有一人知道自己有必胜策略,现在他想要尽可能快的赢,另外一个人则想要尽可能输的慢一点
给你N与K,假设游戏最终持续了X轮,如果FFF赢了,输出X,否则输出-X
注意:1既不是质数也不是合数

输入描述

输入一行,包含两个整数N,K (1 ≤ N ≤ 474747, 1 ≤ K ≤ N)

输出描述

输出一个整数

示例1

输入:

3 2

输出:

1

示例2

输入:

58 1

输出:

0

示例3

输入:

30 3

输出:

-2

示例4

输入:

6 3

输出:

1

示例5

输入:

526 58

输出:

19

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 151ms, 内存消耗: 15464K, 提交时间: 2022-07-22 16:07:28

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=10000009;
ll prime[N],cnt=0;
bool st[N];
void calculate_prime(){
	for(ll i=2;i<=N;i++){
		if(!st[i]) prime[cnt++]=i;
		for(ll j=0;prime[j]<=N/i;j++){
			st[i*prime[j]]=true;
			if(i%prime[j]==0)
				break;
		}
	}
}

int main(){
	calculate_prime();
	bool FFF=true;
	int n,k,m=0;
	scanf("%d%d",&n,&k);
	if(n<=2){
		cout<<0;
		return 0;
	}
	for(ll i=1;prime[i]<=n;i++){
		m++;
		if(prime[i]-prime[i-1]>k+1){
			FFF=false;
		}
	}
	if(n-prime[m]>k){
		cout<<0;return 0;
	}
	if(FFF){
		int pos,ans=0;
		while(1){
			pos=n-k;
			int prm=lower_bound(prime,prime+m,pos)-prime;
			ans++;
			if(prime[prm]<=3) break; 
			n=prime[prm]-1; 
			ans++; 
		}
		printf("%d\n",ans);
	}
	else{
		int ans=0,cnt=m;
		if(n==prime[m]){
			if(n<=prime[m-1]+k) cnt--; 
			else{
				cout<<0;
				return 0;
			}
		}
		while(1){
			if(n<=prime[cnt]+k){
				n=prime[cnt];
			}
			else break;
			ans++;
			int pos=n-k; 
			int prm=upper_bound(prime,prime+m,pos)-prime;
			n=prime[prm]-1;
			cnt=prm-1;
			ans++;
		}
		if(ans) printf("%d\n",-ans);
		else cout<<0;
	}
	return 0;
}

上一题