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 */