• HDU 3404 Switch lights 博弈论 nim积


    http://acm.hdu.edu.cn/showproblem.php?pid=3404 题目

    http://www.doc88.com/p-5098170314707.html 论文 nim积在22页附近

    http://blog.csdn.net/kele52he/article/details/77099890 抄的代码的来源

    根据论文相关部分和自己的理解的介绍。(nim积其实没什么卵用,学这种毒瘤的都有猫病。)

    nim和其实就是异或,想一下之前sg函数或者nim游戏结算的时候,是几堆在一起玩的,异或之后就是这几堆游戏的nim和。

    想一个二维翻硬币游戏,给出正面朝上的硬币的坐标,每次翻两个同排或同列的硬币,其中坐标较大的翻之前必须正面朝上,没法操作的为输。坐标从0开始。

    那么每个位置的sg函数就相当于横纵坐标的nim和,因为每个位置的硬币相当于两个博弈游戏放在一起玩。这个sg函数的计算方式称作x⊕y。

    再想另一个规则的二维翻硬币游戏,给出正面朝上的硬币的坐标,每次必须同时翻四个能作为同一个矩形的四个顶点的硬币,其中列数和排数最大的硬币必须为正面朝上,没法操作的为输。坐标从0开始。(这就是hdu3404的题意)

    那么这次的sg函数就较为复杂,我们把位置(x,y)的的sg函数称为xⓧy。

    ⓧ操作有如下规则。

    1.单位元: xⓧ1=1ⓧx=x;  2.交换律: xⓧy=yⓧx; 

    3.结合律: (xⓧy)ⓧz=(xⓧy)ⓧz;  4.对异或的分配率: (x⊕y)ⓧz=(xⓧz)⊕(yⓧz).

    ⓧ的基本运算性质: 对于x,y<2^(2^a)

    1.xⓧ( 2^(2^a) ) = ( 2^(2^a) )*x;

    2.xⓧy < ( 2^(2^a) );

    3.( 2^(2^a) ) ⓧ( 2^(2^a) )=3/2* ( 2^(2^a) ).

    根据这些基本性质,我们可以得出一个递归求nim积的板子,这里放上这道题的代码。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<iostream>
     6 #include<map>
     7 #include<ctime>
     8 using namespace std;
     9 int n;
    10 int sg[21][21]={};
    11 int f(int,int);
    12 int g(int x,int y){
    13     if(sg[x][y]!=-1)return sg[x][y];
    14     if(!x)return sg[x][y]=1<<y;
    15     if(!y)return sg[x][y]=1<<x;
    16     int ans=1,k=1,t;
    17     int x1=x,y1=y;
    18     while(x||y){
    19         t=1<<k;
    20         if((x^y)&1){
    21             ans*=t;
    22         }
    23         x>>=1;y>>=1;k<<=1;
    24     }
    25     k=1;x=x1;y=y1;
    26     while(x||y){
    27         t=1<<k;
    28         if((x&y)&1){
    29             ans=f(ans,t/2*3);
    30         }
    31         x>>=1;y>>=1;k<<=1;
    32     }return sg[x1][y1]=ans;
    33 }
    34 int f(int x,int y){
    35     if(!x||!y)return 0;
    36     if(x==1)return y;
    37     if(y==1)return x;
    38     int ans=0;
    39     for(int i=x,a=0;i;i>>=1,a++){
    40         if(!(i&1))continue;
    41         for(int j=y,b=0;j;j>>=1,b++){
    42             if(!(j&1))continue;
    43             ans^=g(a,b);
    44         }
    45     }return ans;
    46 }
    47 int main(){
    48     int T;scanf("%d",&T);
    49     memset(sg,-1,sizeof(sg));
    50     while(T-->0){
    51         scanf("%d",&n);
    52         int ans=0,x,y;
    53         for(int i=1;i<=n;i++){
    54             scanf("%d%d",&x,&y);
    55             ans^=f(x,y);
    56         }
    57         if(ans)printf("Have a try, lxhgww.
    ");
    58         else printf("Don't waste your time.
    ");
    59     }
    60     return 0;
    61 }
    View Code
  • 相关阅读:
    迭代器
    闭包函数与装饰器
    pyhton的函数
    文件处理
    Python2和Python3编码的区别
    hdu5080:几何+polya计数(鞍山区域赛K题)
    hdu1695:数论+容斥
    HDU3564 --- Another LIS (线段树维护最值问题)
    hdu1521:排列组合---指数型母函数
    poj1014:母函数+优化
  • 原文地址:https://www.cnblogs.com/137shoebills/p/8337690.html
Copyright © 2020-2023  润新知