11月1日个人训练赛C - Industrial Nim

典型的裸的nim游戏

看过与博弈论有关的文章都知道nim游戏有个结论:

有n堆石头,两个人轮流从这n堆中一堆石头去取出任意数目的石头,最后取光石头者得胜

设第i堆石头ai个石头 ,则 若a1^a2^a3^..^an=0,则先手去石头的人输,反之则赢。

(我只是知道这个结论,不会证明,,暑假的时候看别人的证明看了好久 最后还是是懂非懂! ⊙﹏⊙‖∣)

这题意思是有 n个采石场第i个采石场有mi堆石头,其中第j堆石头的数目为xi+j-1;

设ans为所有堆的石头的数目的异或总和

首先看到这题我没仔细看这题的数据范围,然后我直接把所有的数一个一个枚举出来,异或等到最后结果,

for(int i=1; i<= n; i++)
  for(int j=0; j< m[i]; j++)
  {
   ans^=(x[i]+ j);
  }

等到TLE的才发现一个一个数去异或是不行滴

这时我们可以可以利偶数异或偶数加一的值等于一 去优化计算

最终代码如下:

 
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#include<limits.h>
using namespace std;
__int64 m[111111],x[111111];
int f(__int64 a,__int64 b)
{
 	__int64 ans=0;
	if(a%2!=0)
 	{
		ans^= a;
		a++;
		b--; 
	}
	while(b%4!=0)
	{
		ans^= (a+b-1);
		b--;
	}
	return ans;
}
int main()
{
 int n; 
 while(scanf("%d",&n)!=EOF)
 {
  __int64 ans=0;
  for(int i=1; i<= n; i++)
   scanf("%I64d %I64d",&x[i],&m[i]);
  for(int i=1; i<= n; i++)
  {
    ans^=f(x[i],m[i]);
  }
  if(ans)
   printf("tolik\n");
  else
   printf("bolik\n");    
 }
return 0;
}

 


 

你可能感兴趣的:(CF,博弈论)