> 文章列表 > BZOJ 2940 条纹

BZOJ 2940 条纹

BZOJ 2940 条纹

题目大意

条纹游戏是一个双人的游戏。所需要的物品有一个棋盘以及三种颜色的长方形条纹,这三种颜色分别是红色、绿色和蓝色。红色条纹的尺寸是c×1c\\times 1c×1,绿色条纹的尺寸是z×1z\\times 1z×1,蓝色条纹的尺寸是n×1n\\times 1n×1。这里c,z,nc,z,nc,z,n是正整数,每个游戏者都拥有每种颜色的条纹无限个。

一个棋盘是尺寸为p×1p\\times 1p×1长方形。玩家轮流走,每一步都是由一个游戏者任选一种长方形条纹覆盖到棋盘上,并要求遵循以下规则:

  • 条纹不能伸出棋盘之外
  • 不能覆盖在已有的条纹之上
  • 条纹的边缘必须与棋盘方格的边缘相重叠

第一个不能移动的玩家输。

总共有mmm个棋盘。对于每个棋盘,问先手是否有必胜策略。有则输出111,否则输出222

数据范围

1≤c,z,n≤1000,1≤m≤1000,1≤p≤10001\\leq c,z,n\\leq 1000,1\\leq m\\leq 1000,1\\leq p\\leq 10001c,z,n1000,1m1000,1p1000

题解

sg[i]sg[i]sg[i]表示棋盘为i×1i\\times 1i×1时的状态。根据不同条纹的放法,可以得出转移式

sg[i]=mex{sgj⊕sgi−j−c,sgj⊕sgi−j−z,sgj⊕sgi−j−n}sg[i]=mex\\{sg_j\\oplus sg_{i-j-c},sg_j\\oplus sg_{i-j-z},sg_j\\oplus sg_{i-j-n}\\}sg[i]=mex{sgjsgijc,sgjsgijz,sgjsgijn}

那么,我们可以枚举i,ji,ji,j,用O(p2)O(p^2)O(p2)求出所有sgisg_isgi。接下来,对于每一个ppp,可以O(1)O(1)O(1)求出sgpsg_{p}sgp

时间复杂度为O(p2+m)O(p^2+m)O(p2+m)

code

#include<bits/stdc++.h>
using namespace std;
int a,b,c,m,z[1005],sg[1005];
int main()
{scanf("%d%d%d",&a,&b,&c);for(int i=1;i<=1000;i++){for(int j=0;j<=1000;j++) z[j]=0;for(int j=0;j<=i;j++){if(a+j<=i) z[sg[j]^sg[i-j-a]]=1;if(b+j<=i) z[sg[j]^sg[i-j-b]]=1;if(c+j<=i) z[sg[j]^sg[i-j-c]]=1;}int x=0;for(;z[x];x++);sg[i]=x;}scanf("%d",&m);for(int i=1,x;i<=m;i++){scanf("%d",&x);if(sg[x]) printf("1\\n");else printf("2\\n");}return 0;
}