SG函数 BZOJ 1188 && BZOJ 1874

        说好的这个星期要搞数学和几何……

        两题都很简单,暴力求出SG值即可

        还有注意一下xor时要打括号,不然各种意外错误%>_<%

BZOJ 1188

#include <cstdio>
#include <cstring>

using namespace std;

const int MAXN = 30;
const int MAXP = 10001;

int t,n;
int Sg[MAXN];
int data[MAXN];

int SG(int x)
{
	if (x == n) return 0;
	if (Sg[x] != -1) return Sg[x];
	bool vis[MAXP];
	memset(vis,false,sizeof(vis));
	for (int i=x+1;i<=n;i++)
	    for (int j=i;j<=n;j++) vis[SG(i)^SG(j)] = true;
	for (int i=0;;i++) if (!vis[i]) return Sg[x] = i;
}

int main()
{
	scanf("%d",&t);
	while (t--)
	{
		memset(Sg,-1,sizeof(Sg));
		scanf("%d",&n);
		for (int i=1;i<=n;i++) scanf("%d",&data[i]);
		int ans =0, cnt = 0;
		for (int i=1;i<=n;i++) if (data[i]&1) ans ^= SG(i);
		for (int i=1;i<=n;i++)
		    for (int j=i+1;j<=n;j++)
		        for (int k=j;k<=n;k++)
		            if ((ans^SG(i)^SG(j)^SG(k)) == 0)
		            {
		            	cnt++;
		            	if (cnt == 1) printf("%d %d %d\n",i-1,j-1,k-1);
		            }
		if (!cnt) printf("-1 -1 -1\n");
		printf("%d\n",cnt);
	}
	return 0;
}

BZOJ 1874

#include <cstdio>
#include <cstring>

using namespace std;

const int MAXN = 1001;
const int MAXA = 1001;

int n,m;
int data[MAXN],can[MAXA];
int SG[MAXA];

inline int GetSG(int x)
{
	if (x <= 0) return SG[0] = 0;
	if (SG[x] != -1) return SG[x];
	bool vis[MAXA];
	memset(vis,false,sizeof(vis));
	for (int i=1;i<=m && x >= can[i];i++) vis[GetSG(x-can[i])] = true;
	for (int i=0;;i++) if (!vis[i]) return SG[x] = i;
}

int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++) scanf("%d",&data[i]);
	scanf("%d",&m);
	for (int i=1;i<=m;i++) scanf("%d",&can[i]);
	memset(SG,-1,sizeof(SG));
	int ans = 0,cnt = 0, first;
	for (int i=1;i<=n;i++) ans ^= GetSG(data[i]);
	if (ans == 0) printf("NO\n");
	else
  	    for (int i=1;i<=n;i++) 
		{
			int temp = ans^GetSG(data[i]);
			for (int j=1;j<=m && data[i] >= can[j];j++) if ((GetSG(data[i]-can[j])^temp) == 0) 
			{
			    printf("YES\n%d %d\n",i,can[j]);
			    return 0;
			}
		}
	return 0;	
} 





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值