zoukankan      html  css  js  c++  java
  • HDU3544 Alice's Game && POJ 2960 S-Nim(SG函数)

    题意:

    有一块xi*Yi的矩形巧克力,Alice只允许垂直分割巧克力,Bob只允许水平分割巧克力。具体来说,对于Alice,一块巧克力X i * Y i,只能分解成a * Y i和b * Y i其中a + b = X i和a, b > 0。对于Bob,一块巧克力X i * Y i,只能分解成X i * a和X i * b其中a + b = Y i和a ,b > 0。(每次切割只能以整数单位来切,例如一个宽为3的巧克力,你垂直切只能切成一个1,2而不能切成两个1.5)

    谁最后不能操作了,谁就输了

    题解:

    根据题意我们只需要找到在给出的巧克力中他们两个人能走的最大步数,然后对比一下就可以了;但是另一个人的步数是和前一个人个操作有关

    例如一个4*4的巧克力,如果每一次Alice都以1来切割(第一次1 3,第二次1 1 2,第三次1 1 1 1),这样的话Bob每一次切割宽为1的巧克力的话,他一共能走3*4=12步。但是如果每次Alice按照总宽度的一半来切割的话,那么Alice还是走4步(先切成2 2,然后再找每一个2来切),但是Bob就只能走2步

    而且Alice肯定想让Bob走最小步数,因为Bob步数越大Alice就越难赢,所以每次Alice按照总宽度一半来切就是最优了

    代码:

     1 //参考:https://blog.csdn.net/qq_34374664/article/details/52959986
     2 #include <iostream>
     3 
     4 #include <cstdio>
     5 
     6 #include <cstring>
     7 
     8 #include <algorithm>
     9 
    10 using namespace std;
    11 
    12 const int maxn = 1e9 + 7;
    13 
    14 int main()
    15 
    16 {
    17 
    18     int x, y, n, t, Case = 0;
    19 
    20     scanf("%d", &t);
    21 
    22     while(t--)
    23 
    24     {
    25 
    26         long long ansx = 0, ansy = 0;
    27 
    28         scanf("%d", &n);
    29 
    30         for(int i = 1; i <= n; i++)
    31 
    32         {
    33 
    34             scanf("%d%d", &x, &y);
    35 
    36             while(x > 1 && y  > 1)
    37 
    38             {
    39 
    40                 x /= 2;
    41 
    42                 y /= 2;
    43 
    44                 ansx++;
    45 
    46                 ansy++;
    47 
    48             }
    49 
    50             if(x == 1) ansy += y - 1;
    51 
    52             if(y == 1) ansx += x - 1;
    53 
    54         }
    55 
    56         if(ansx <= ansy) printf("Case %d: Bob
    ", ++Case);
    57 
    58         else printf("Case %d: Alice
    ", ++Case);
    59 
    60  
    61 
    62     }
    63 
    64  
    65 
    66  
    67 
    68     return 0;
    69 
    70 }
    View Code

    POJ 2960 S-Nim题意:

    给你n堆石子,你每次只能取一定数量的石子,这个一定数量每个样例第一行就会输入;谁最后不能取石子谁就输了

    题解:

    很明显的SG函数,把第一个样例讲一下

    2 2 5   //第一个数是k,后面输入k个数,每个数就是限制你每次只能取多少石子
    3         //下面有多少行询问
    2 5 12      //第一个数就是有多少堆石子,后面就是每一堆石子的数量
    3 2 4 7
    4 2 3 7 12

    对于5 12 这两堆石子我们可以向尼姆博弈一样先处理一堆石子,之后再让它们相互异或

    SG(0)=0   //初始化

    SG(1)=0

    SG(2)=mex{SG(0)}=1

    SG(3)=mex{SG(1)}=1

    SG(4)=mex{SG(2)}=0

    SG(5)=mex{SG(0),SG(3)}=2

    SG(6)=mex{SG(1),SG(4)}=1

    SG(7)=mex{SG(2),SG(5)}=0

    SG(8)=mex{SG(6),SG(3)}=0

    SG(9)=mex{SG(7),SG(4)}=1

    SG(10)=mex{SG(8),SG(5)}=1

    SG(11)=mex{SG(9),SG(6)}=0

    SG(12)=mex{SG(10),SG(7)}=2

    所以两堆石子的结果就是SG(5)^SG(12)=0,所以这个时候就输了

    那么肯定是每一组样例先打表对SG函数预处理

    代码:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 #pragma comment(linker, "/STACK:102400000,102400000")
     8 #define ls i<<1
     9 #define rs ls | 1
    10 #define mid ((ll+rr)>>1)
    11 #define pii pair<int,int>
    12 #define MP make_pair
    13 typedef long long LL;
    14 const long long INF = 1e18+1LL;
    15 const double Pi = acos(-1.0);
    16 const int N = 5e5+10, M = 2e5+20, mod = 1e9+7, inf = 2e9;
    17 
    18 int k,sg[N],s[N],vis[N];
    19 char A[N];
    20 int main() {
    21         while(scanf("%d",&k)!=EOF) {
    22             if(k == 0) break;
    23             for(int i = 1; i <= k; ++i) scanf("%d",&s[i]);
    24             sg[0] = 0;
    25             for(int i = 1; i <= 10000; ++i) {   //预处理打表找出SG的值
    26                 for(int j = 0; j <= 100; ++j) vis[j] = 0;
    27                 for(int j = 1; j <= k; ++j) {
    28                    if(i >= s[j] && sg[i - s[j]] <= 100) vis[sg[i - s[j]]] = 1;  //这一步就是判断从这个点都能到哪
    29                 }
    30                 for(int j = 0; j <= 100; ++j) {  //这一步相当于找不在mex中最小的值
    31                     if(!vis[j]) {
    32                         sg[i] = j;
    33                         break;
    34                     }
    35                 }
    36             }
    37             int q,cnt = 0;
    38             scanf("%d",&q);
    39             while(q--) {
    40                 int x,y,ans = 0;
    41                 scanf("%d",&x);
    42                 while(x--) {
    43                     scanf("%d",&y);
    44                     ans ^= sg[y];    //得到每一堆石子的SG值之后再异或处理就可以了
    45                 }
    46                 if(ans) printf("W");
    47                 else printf("L");
    48             }
    49             printf("
    ");
    50         }
    51     return 0;
    52 }
    View Code
  • 相关阅读:
    Java日期工具类,Java时间工具类,Java时间格式化
    js 小数取整,js 小数向上取整,js小数向下取整
    Tomcat v7.0 Server at localhost are already in use,tomcat提示端口被占用,tomcat端口已经被使用,tomcat端口占用
    easyui datebox 时间限制,datebox开始时间限制结束时间,datebox截止日期比起始日期大
    Jquery Easyui验证扩展,Easyui验证,Easyui校验,js正则表达式
    根据日期字符串获取星期几,日期获取星期,时间获取星期,js获取星期
    jquery easyui combobox 级联及触发事件,combobox级联
    js计算2个日期相差的天数,两个日期相差的天数,日期相隔天数
    设置checkbox选中,设置radio选中,根据值设置checkbox选中,checkbox勾选
    layer弹出层不居中解决方案,layer提示不屏幕居中解决方法,layer弹窗不居中解决方案
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/11371453.html
Copyright © 2011-2022 走看看