小红的好子序列 | 算贡献 组合数性质 Go
小红的好子序列
https://www.nowcoder.com/practice/9b6955921efc4f0b97701641e0402a29
题意
小红定义一个字符串是好串,当且仅当每个字母出现的次数均为偶数。小红拿到了一个字符串,她想知道该字符串有多少子序列是好串?
思路
题目里求的是满足xxx条件的子序列的个数,那每个字母的贡献都可以单独拿出来算了,比如题目样例的ababa 字符串,a出现了3次,b出现了2次,那么对于a来说,从里面选偶数个都可以构成一种答案,对于b来说也同理。
a和b的选择都是独立的,不难想到相乘就是答案。所以先用哈希表统计出每个字母出现的次数。
对于一个字母来说,出现的次数为x,其对答案的贡献是c[x][0] + c[x][2] + c[x][4] + …… ,即组合数里所有的偶数项加起来,根据组合数的性质
C(n,0)+C(n,1)+C(n,2)+...+C(n,r)+....+C(n,n)=2n
C(n,0)+C(n,2)+C(n,4)+...=C(n,1)+C(n,3)+C(n,5)+...=2(n-1)
所以直接算2n-1次方就可以了
注意最后要把所有字母都不选的情况去掉
在算的时候不能去,因为这个字母不选的时候,选别的字母也可以构成合法的答案
代码
package main import ( "fmt" ) func main() { const MOD = 1_000_000_007 var s string fmt.Scan(&s) mp := make(map[rune]int) for _,ch := range s { mp[ch] ++ } ans := 1 for _,v := range mp { tmp := 1 //一个字母出现了v次 对答案的贡献是多少 //可以从其中选任意2的倍数个 C[v][0] + C[v][2] + C[v][4] //2^(n-1) for i := 1; i <= v-1 ; i ++ { // if i % 2 != 0 { // continue // } tmp = tmp * 2 % MOD } ans = ans * tmp % MOD } fmt.Println(ans-1) //减去所有字母都不选 }#牛客创作赏金赛#
15天大厂真题带刷Go题解 文章被收录于专栏
15天大厂真题带刷Golang题解