题意:
有n个石头,FFF和GGG轮流对这堆石头进行操作,每一次可以取[1,k]个石头,但FFF取完后石头数为质数,GGG取完后石头数为合数,如果FFF赢了,则输出回合数,如果GGG赢了,则输出回合数的相反数。
注意:1既不是质数,也不是合数。
胜利者会尽可能的快点赢,输者会尽可能的慢点输。
思路:
快点赢则胜利者会尽可能的多取点,慢点输则输者会尽可能的少取点。
我们首先要知道谁赢,如果第一步都不能走则FFF输,然后如果石头数内有两质数之间相差大于k+1则FFF一定输(因为GGG取成大质数-1时FFF无法取),否则FFF一定赢(因为FFF取到小于等于3时GGG无法取)
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf=1e9+7;
int pa[1000005], sum[1000005], prime[10000005], ji=0;
int main()
{
int n, k, ans=0;
scanf("%d%d",&n,&k);
pa[0]=pa[1]=1;
for(int i=2; i*i<=1000000; i++)
{
if(!pa[i])
{
for(int j=i*i; j<=1000000; j=j+i)
{
pa[j]=1;
}
}
}
for(int i=2;i<=1000000;i++)
{
if(!pa[i])
{
prime[ji++]=i;
}
}
int flag=0, ti=-1, zui;
for(int i=1;prime[i]<n;i++)
{
if(prime[i]-prime[i-1]>k+1)
{
flag=1;
ti=i;
}
zui=i;
}
if(n<=2||n-prime[zui]>k)
{
ans=0;
}
else if(flag==0)
{
for(int i=n;;)
{
if(i-k<=3)
{
ans++;
break;
}
int ki=lower_bound(prime,prime+ji,i-k)-prime;
i=prime[ki];
ans++;
if(!pa[i-1])
{
break;
}
i--;
ans++;
}
}
else
{
for(int i=n;;)
{
int ki=lower_bound(prime,prime+ji,i)-prime-1;
if(i-prime[ki]>k)
{
break;
}
i=prime[ki];
ans--;
if(i-k<=prime[ti]-1)
{
ans--;
break;
}
if(!pa[i-k])
{
i=i-k+1;
}
else
{
i=i-k;
}
ans--;
}
}
printf("%d\n",ans);
return 0;
}

京公网安备 11010502036488号