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

全部评论

相关推荐

书海为家:实习是成为大厂正式员工很好的敲门砖,看您的简历中有一段实习经历,挺好的。我来给一点点小建议,因为毕竟还在学校不像工作几年的老鸟有丰富的项目经验,面试官在面试在校生的时候更关注咱们同学的做事逻辑和思路,所以最好在简历中描述下自己实习时做过项目的完整过程,比如需求怎么来的,你对需求的解读,你想到的解决办法,遇到困难如何找人求助,最终项目做成了什么程度,你从中收获了哪些技能,你有什么感悟。
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
正在热议
更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务