BZOJ4702 装箱游戏

来源:互联网 发布:麒麟外推软件 编辑:程序博客网 时间:2024/06/05 19:18

一眼sg函数……

但是c太大了,不过我们发现如果n>根号c,那么如果m>1的话一定是先手必胜的,所以n>根号c的部分只算m=1的就行了

考虑一下什么时候能平,当且仅当n初始得1,且对于任意的n=2,m=i,i>=初始的m的情况,都是先手必胜,那么两人都只能一直加m,然后就会平

复杂度(m sqrt c)

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<ctime>#include<cmath>#include<algorithm>#include<iomanip>#include<vector>#include<map>#include<set>#include<bitset>#include<queue>#include<stack>using namespace std;#define MAXN 100010#define MAXM 35#define INF 1000000000#define MOD 1000000007#define eps 1e-8#define ll long longint sg[MAXN][MAXM];int n,m,c;int N;int lim[MAXN];int SG(int x,int y){if(x>=N&&y==1){return ((c^x)&1)^1;}if(y>lim[x]){return 1;}return sg[x][y];}int main(){int i,j,k;int tmp;scanf("%d",&tmp);while(tmp--){memset(lim,0,sizeof(lim));scanf("%d%d%d",&n,&m,&c);N=int(ceil(sqrt(c)));if(n>=N){if((c^n)&1){printf("Bob\n");}else{printf("Alice\n");}continue ;}if(n==1&&pow(2.0,1.0*m)>=c){printf("Draw\n");continue ;}for(i=N-1;i>=n;i--){if(i==1){int flag=-1;for(j=m;j<=max(1,lim[2]);j++){if(SG(i+1,j)==0){if(((j^m)&1)^1){flag=1;}else{flag=0;}break;}}if(flag==-1){printf("Draw\n");}else{printf(flag?"Alice\n":"Bob\n");}break;}ll now=1;for(lim[i]=0;now<c;lim[i]++){now*=i;}lim[i]--;for(j=lim[i];j>=m;j--){for(k=0;;k++){if(SG(i+1,j)!=k&&SG(i,j+1)!=k){sg[i][j]=k;break;}}}}if(n!=1){printf(sg[n][m]?"Alice\n":"Bob\n");}}return 0;}/*11 2 9*/


0 0
原创粉丝点击