AT693 文字列 (计数 dp)

Description

构造一个小写字母构成的字符串,使小写字母 i i i 出现了 f r e q i freq_i freqi 次,且相同字母不能相邻,求方案数并对 1 0 9 + 7 10^9 + 7 109+7 取模。

1 ≤ f r e q i ≤ 10 1 \leq freq_i \leq10 1freqi10

Solution

计数 dp,先找出所有 f r e q i > 0 freq_i > 0 freqi>0 的小写字母,一个个插入字符串中。因为答案与插入顺序无关,所以我们按 aabbbccddddeeefgg 这样的顺序插入。在插入的过程中,难免会出现不合法的情况。举个栗子,如 *a a*c*b*d d d*b b*,不合法的位置有 4 4 4 个,即为空格。合法位置有 6 6 6 个,即为 *。可以发现三个性质:

  1. S S S 的合法位置数与不和法位置数之和为 ∣ S ∣ + 1 |S| + 1 S+1
  2. 没有两个合法位置或不合法位置是相邻的。
  3. 每一个合法位置可以插入任意个字母,也可以不插。

可以想到状态,令 f i , j f_{i,j} fi,j 为插入了所有的小写字母 i i i 后,有 j j j 个不合法位置的方案数。赋初值,将第一段 f r e q i > 0 freq_i > 0 freqi>0 的小写字母全部插入后的 f i , j = 1 f_{i,j} = 1 fi,j=1。如 bbbccddddeeefggbbb 是第一段,于是 f b − a = 1 , 2 = 1 f_{b - a = 1, 2} = 1 fba=1,2=1

枚举 i i i,和 f i − 1 , k f_{i-1,k} fi1,k 中的 k k k,意味着 f i , j f_{i,j} fi,j 会从 f i − 1 , k f_{i-1,k} fi1,k 转移。考虑将所有的小写字母 i i i 插入到字符串中,无非是插入到合法的位置或不合法的位置。所以再枚举一个 g o o d good good b a d bad bad,如字面意思, g o o d good good 为插入到合法位置的段数 b a d bad bad 为插入到不合法位置的段数。在枚举的过程中,同时维护一个在加入字母前的字符串长度 s u m sum sum,用于确定枚举范围。

考虑一个问题:将所有小写字母 i i i 加入字符串,有 g o o d good good 段字母插入了合法位置,有 b a d bad bad 段字母插入了不合法位置。那么新产生了多少不合法的位置,又减少了多少不合法的位置?

减少的就是 g o o d good good 个。因为插入的字母分成了 g o o d + b a d good + bad good+bad 段,那么新产生了 g o o d + b a d − 1 good + bad - 1 good+bad1 个间隔。如果 g o o d + b a d = 1 good+bad=1 good+bad=1,那么成为不合法位置的位置一共有 f r e q i − 1 freq_i - 1 freqi1 个,所以增加了 f r e q i − 1 − g o o d − b a d + 1 = f r e q i − g o o d − b a d freq_i - 1 - good - bad + 1 = freq_i - good - bad freqi1goodbad+1=freqigoodbad 个不合法位置。

所以, j = k − b a d + f r e q i − g o o d − b a d j = k - bad + freq_i - good - bad j=kbad+freqigoodbad

转移方程如下,其中 s u m + 1 − k sum + 1 - k sum+1k 为根据性质一求出的合法位置个数, ( n m ) n \choose m (mn) 为组合数可以预处理。可以发现,转移方程是根据乘法原理将每一部分相乘,其中的 ( f r e q i − g o o d − b a d f i − 1 ) {freq_i - good - bad} \choose {f_i - 1} (fi1freqigoodbad) 是什么呢?因为我们是把一段段相同的字母插入合法的位置或不合法的位置,不仅要乘上几段字母插入到哪几个位置的方案数,还要乘上所有的字母 i i i 是如何分成了几段字母的方案数。把一段字母看成一个盒子,每个字母看成一个球,一共 g o o d + b a d good + bad good+bad 个盒子, f r e q i freq_i freqi 个球,问题转换成求每个盒子至少一个球的方案数。套上插板法公式即可。

f i , j = f i , j + f i − 1 , k × ( b a d k ) × ( g o o d s u m + 1 − k ) × ( g o o d + b a d − 1 f r e q i − 1 ) f_{i,j} = f_{i,j} + f_{i - 1,k} \times {{bad}\choose{k}} \times {{good}\choose{sum + 1 - k}} \times {{good + bad -1} \choose{freq_i - 1}} fi,j=fi,j+fi1,k×(kbad)×(sum+1kgood)×(freqi1good+bad1)
a n s = f n − 1 , 0 ans = f_{n-1,0} ans=fn1,0

时间复杂度 O ( n 3 ) O(n^3) O(n3),其中 n = ∑ i = 0 25 f r e q i n = \sum_{i=0}^{25} freq_i n=i=025freqi

Code

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 500 + 5, p = 1e9 + 7;
inline int read() {
    int X = 0,w = 0; char ch = 0;
    while(!isdigit(ch)) {w |= ch == '-';ch = getchar();}
    while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48),ch = getchar();
    return w ? -X : X;
}
int f[26][N], C[N][N], freq[N], sum, fir, n;
signed main() {
	for (int i = 0; i < 26; i++) {
		freq[n] = read();
		if (freq[n]) n++;
	}
	for (int i = 0; i <= 300; i++) {
        C[i][0] = C[i][i] = 1;
        for (int j = 1; j < i; j++) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % p;
	}
    f[0][freq[0] - 1] = 1, sum = freq[0];
    for (int i = 1; i < n; i++) {
    	for (int k = 0; k <= sum; k++) 
			for (int bad = 0; bad <= min(freq[i], k); bad++)
				for (int good = 0; good + bad <= freq[i] && good <= sum + 1 - k; good++) {
					int j = k - bad + freq[i] - good - bad;
					f[i][j] = (f[i][j] + f[i - 1][k] * C[k][bad] % p * C[sum + 1 - k][good] % p 
					* C[freq[i] - 1][good + bad - 1] % p) % p;
				}
		sum += freq[i]; 
    }	
	printf("%lld\n", f[n - 1][0]);
	return 0;
}  
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值