HDU 5229 博弈思维

题意:总共有N 个串, 从中拿出2个串来,两人轮流进行两种操作

操作1:   将两个串中随机拿出一个非空串,删掉其末尾字母

操作2:   如果两个串相同且非空才能执行该操作,清空两个串;

谁面临无法执行操作时 ,  判为输,  两人足够机灵

题解:明显  如果两个串相同则必定先生赢,两个人为了避免对手拿到必胜状态一定会尽量使两个串差距大。策略为拿两个串中最小的串,既能使对家面临两个串都为空的状态或者是两个串不相等的非必胜状态。两人同时采取最优策略,  那么很明显最终的输赢只和取的A和B 串长有关,   A的长度加上B的长度为奇数,先手胜, 否则后手赢。 还有一种情况就是初始状态A串和B串相等,  那么先手胜。所以只需要跑一遍循环记录之前出现的奇数串和偶数串数目和与之相同串的数目 ,  便可以求出胜率




太久没动脑子了 ,   题目想不出来, 看了官方题解才明白该如何做,  加油吧

代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<map>
using namespace std;
map<string, int> mymap;
int gcd(int a, int b)
{
    if(b == 0)  return a;
    return gcd(b, a%b);    
}
int main()
{
     int T, n;
     char s1[210005];
     scanf("%d", &T);
     
     while(T--)
     {
       scanf("%d", &n);
       int sum = 0, ou , ji;
       ou = ji = 0, sum = 0;
       mymap.clear();
       for(int i = 1; i <= n; i++)
       {
          scanf("%s", s1);
          if(mymap[s1]) sum += mymap[s1];
          mymap[s1] ++;
          int len = strlen(s1);
          if(len & 1)  sum += ou, ji++;
          else sum += ji, ou++;        
       }     
       int kk = (n*(n-1))/2;  
       int k = gcd(sum, kk);
       printf("%d/%d\n", sum/k, kk/k);     
     }    
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值