题意:
有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; }