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

全部评论

相关推荐

2024-12-21 10:42
已编辑
江西软件职业技术大学 Java
新宿站不停:该提升学历就提升学历,菜了就多练。没事找牛马公司虐自己是吧? 谁没事说自己“经验少”,这不自己把自己塞剎鼻hr嘴里找🐴吗
点赞 评论 收藏
分享
KPLACE:首先是板面看起来不够,有很多奖,比我厉害。项目要精减,大概详细描述两到三个,要把技术栈写清楚,分点,什么算法,什么外设,怎么优化,不要写一大堆,分点,你写上去的目的,一是让别人知道你做了这个知识点,然后在面试官技术面的时侯,他知道你会这个,那么就会跟你深挖这个,然后就是个人评价改为专业技能
点赞 评论 收藏
分享
评论
2
收藏
分享
牛客网
牛客企业服务