AtCoder Grand Contest 019 B - Reverse and Compare【思维】

AtCoder Grand Contest 019 B - Reverse and Compare

题意:给定字符串,可以选定任意i、j且i<=j(当然i==j时没啥卵用),然后翻转i到j的字符串,问能组成多少种不同的字符串。

  tourist出的题。。感觉好棒,虽然简单,但我就是不知道怎么弄,感觉思维好匮乏。

  首先,如果Si=Sj,那么反转i到j和翻转i+1到j-1是一样的,也就是这种翻转不会贡献更多的答案。那么其实只要求i<j且Si!=Sj的个数就行了,当然,本身不变也是一种答案。求解i<j且Si!=Sj的个数可以从总的i<j的翻转个数中减去不合法的,也就是Si==Sj的。总的个数就是字符串长度len*(len-1)/2,因为可以这样想,s[0]能与后面len-1个字符组成字串翻转,s[1]能跟后面len-2个字符组成字符串翻转...,所以总结果就是len-1+len-2+len-3+...+1=len*(len-1)/2。然后统计每个字符出现的次数cnt(c),每种字符组成的不合法种数是cnt(c)*(cnt(c)-1)/2,跟上面道理一样。所以答案就是:

          1+len*(len-1)/2-∑cnt(c)*(cnt(c)-1)/2

  看来数据类型尽量要统一,刚开始设len为int类型就WA了,全是long long就对了。

  

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<map>
 6 using namespace std;
 7 typedef long long ll;
 8 map<int, ll> mp;
 9 char s[200010];
10 
11 int main()
12 {
13     cin >> s;
14     ll len = strlen(s);
15     for (int i = 0; i < len; i++)
16         mp[s[i] - 'a']++;
17     ll ans = 1;
18     ans += len*(len - 1) / 2;
19     for (int i = 0; i < 26; i++)
20         if (mp[i]) ans -= mp[i] * (mp[i] - 1) / 2;
21     cout << ans << endl;
22     return 0;
23 }

 

posted @ 2017-08-27 14:21  ╰追憶似水年華ぃ╮  阅读(292)  评论(0编辑  收藏  举报