HDU 5229 ZCC loves strings 博弈

题目链接:

hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5229

bc:http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=582&pid=1002

题解:

设字符串a,b;

结论:先手胜的充分必要条件是|a|+|b|为奇数或a==b。

证明:

数学归纳法:

|a|+|b|=0;时,先手败,结论成立

假设|a|+|b|<p时结论成立,现在分类讨论|a|+|b|的情况:

p为偶数:

如果a=b,则先手直接采取方案b取胜,否则,先手只能执行方案A必败。

p为奇数:

先手只要用方案a取走一个,且保证取走之后a!=b(取较短的那个,当较短为0时,去另一个),那么就能保证必胜。

综上所述,结论成立。

---------------------------------我是分割线----------------------------------

对于当前输入串,统计它之前与它相等的串的个数x和长度与它不同奇偶的串的个数y,累加它对答案的贡献x+y,线性扫一遍就好了。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<map>
 5 using namespace std;
 6 
 7 const int maxn=1e5+10;
 8 
 9 int odd[2];
10 char str[maxn];
11 int n;
12 map<string,int> mymap;
13 
14 void init(){
15     mymap.clear();
16     memset(odd,0,sizeof(odd));
17 }
18 
19 int gcd(int a,int b){ return b==0?a:gcd(b,a%b); }
20 
21 int main(){
22     int tc;
23     scanf("%d",&tc);
24     while(tc--){
25         init();
26         int ans=0;
27         scanf("%d",&n);
28         for(int i=0;i<n;i++){
29             scanf("%s",str);
30             int o=strlen(str)&1;
31             ans+=odd[!o];
32             odd[o]++; 
33             
34             //str不需要是string类型! 
35             ans+=mymap[str];
36             mymap[str]++;
37         }
38         int demo=n*(n-1)/2;
39         int g=gcd(ans,demo);
40         if(ans==0) printf("0/1\n");
41         else printf("%d/%d\n",ans/g,demo/g);
42     }
43     return 0;
44 }
45 
46 /*
47 2
48 ab
49 bc
50 */

 

posted @ 2016-04-13 18:02  fenicnn  阅读(201)  评论(0编辑  收藏  举报