小红的好子序列 | 算贡献 组合数性质 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题解

全部评论

相关推荐

03-21 08:46
已编辑
门头沟学院 C++
一个什么都不会的学生:当你有硕士学历的时候HR会说就是比本科生强
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务