[nh云课堂]周中测试

T1

给一个长度是 nn 的仅含有小写字母的字符串ss,求 ss 的不同非空子序列一共有多少个,答案对 10000000071000000007 取模。

下面给出子序列定义:

字符串的子序列是经由原字符串删除 kk 个(kk 有可能等于 00)字符但不改变剩余字符相对位置的一个新字符串。

1n20001\leq n\leq 2000


思路

考虑 dp。定义 dpidp_i 为以第 ii 个字符为结尾的不重复子序列数量。如果将 dpi=i=1i1dpidp_i=\sum\limits_{i=1}^{i-1}dp_i。就会出现重复的情况。

例如 ABAB\tt{ABAB}a1,a2a_1,a_2a3,a4a_3,a_4 都是 AB\tt{AB}。就会被讨论两次,这是错误的。


现在来考虑正确的状态转移方程,dpidp_i 可以从 dpjj=1i1dp_{j}|j=1\dots i-1 转移过来。

考虑转移的方式,考虑到状态不重复的定义。既然如此,直接将原序列的末尾替换(删掉再加上)掉就可以了,此时如果 si=sjs_i=s_j ,替换后还是原来的序列,不能转移。

需要注意的是,我们还可以添加 sjs_j,组成 s1sjs_1\sim s_j。这样的序列一定合法。

不能添加 jj

例如 ABCD\tt{ABCD}。如果将 AB\tt{AB} 加上 D\tt{D},和 ABC\tt{ABC} 替换 D\tt{D} 重复了。而 ABC\tt{ABC} 加上 D\tt{D} 是不会重复的,因为原本没有一个长度为 44 的序列。


综上所述,状态转移方程为:

dpi=dpjj=1...i1&sjsidp_i=dp_j|j=1...i-1 \And s_j \neq s_i

实现

我们可以将 dp01dp_0\gets 1,在转移时,就可以实现添加的操作。


代码

#include<bits/stdc++.h>
using namespace std;
const int N = 2e3+10,Mod=1e9+7;
char ch[N];
int dp[N]={1},ans;
int main() {
	cin>>ch+1;
	int n=strlen(ch+1);
	for(int i=1;i<=n;i++) {
		for(int j=0;j<i;j++)
			if(ch[i]!=ch[j]) dp[i]=(dp[i]+dp[j])%Mod;
		ans=(ans+dp[i])%Mod;
	}
	cout<<ans;
	return 0;
}

T2

组合数问题

前置知识:杨辉三角。

由于 kk 已经确定。

本文作者:cjrqwq

本文链接:https://www.cnblogs.com/yfzqwq/p/18492787

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   cjrqwq  阅读(2)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
展开
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.