codeforces 645 E. Intellectual Inquiry
一个字符串,由前k个字母组成,长度为m + n,其中前m个字符已经确定,后面n个由你自由选择,
使得这个串的不同的子序列的个数最多,空串也算一个子序列。
1 <= m <= 10^6,0 <= n <= 10^6,1 <= k <= 26
首先,我们考虑n = 0的情况,
问题就为给定一个字符串,求它有多少个不同的子序列。
pre[i]表示字母i最后出现的位置,初始化为0
f[i]表示以第i个字符结尾的与前面已经出现的子序列都不同的子序列个数
g[i] = ∑0<=j<=if[j]
则我们知道f[i] = ∑pre[i]<=j<=i-1f[j]
则 if pre[i] == 0 then f[i] = g[i-1]
if pre[i] > 0 then f[i] = g[i-1] - g[pre[str[i]]-1]
答案就是g[m]
那如果n > 0 呢?
从f的递推式我们知道,要使得f[i]最大,i处填的字符应该是pre值最小的i
那么我们接着遍历,每次拿pre最小的字符,更新f和pre值
最终答案就是g[n + m]
代码:
//File Name: cf645E.cpp
//Created Time: 2017年01月05日 星期四 13时53分24秒 #include <bits/stdc++.h>
#define LL long long
#define fir first
#define sec second
#define pii pair<int,int>
using namespace std;
const int MAXN = + ;
const int P = (int)1e9 + ;
LL f[MAXN],g[MAXN];
char str[MAXN];
int pre[];
set<pii> rem;
LL solve(int n,int k){
int m = strlen(str + );
memset(pre,,sizeof(pre));
f[] = g[] = ;
for(int i=;i<=m;++i){
int v = str[i] - 'a';
if(pre[v] == )
f[i] = g[i - ];
else
f[i] = (g[i - ] - g[pre[v] - ] + P) % P;
g[i] = (g[i - ] + f[i]) % P;
pre[v] = i;
// printf("i = %d f = %lld g = %lld\n",i,f[i],g[i]);
}
rem.clear();
for(int i=;i<k;++i)
rem.insert(pii(pre[i],i));
for(int i=m+;i<=m+n;++i){
// puts("ffff");
pii now = *rem.begin();
int pos = now.fir,v = now.sec;
if(pos == )
f[i] = g[i - ];
else
f[i] = (g[i - ] - g[pos - ] + P) % P;
g[i] = (g[i - ] + f[i]) % P;
pre[v] = i;
rem.erase(rem.begin());
rem.insert(pii(i,v));
}
// for(int i=0;i<=m+n;++i)
// printf("i = %d f = %lld\n",i,f[i]);
return g[m + n];
}
int main(){
int n,k;
scanf("%d %d",&n,&k);
scanf("%s",str + );
printf("%lld\n",solve(n,k));
return ;
}
codeforces 645 E. Intellectual Inquiry的更多相关文章
- Codeforces 645E. Intellectual Inquiry(DP,贪心)
Codeforces 645E. Intellectual Inquiry 题意:给定一串字符,由前k个小写拉丁字母组成,要求在该字符串后面补上n个字符(也从前k个小写拉丁字母里面选),使得最后得到的 ...
- CROC 2016 - Elimination Round (Rated Unofficial Edition) E. Intellectual Inquiry 贪心 构造 dp
E. Intellectual Inquiry 题目连接: http://www.codeforces.com/contest/655/problem/E Description After gett ...
- CROC 2016 - Elimination Round (Rated Unofficial Edition) E - Intellectual Inquiry dp
E - Intellectual Inquiry 思路:我自己YY了一个算本质不同子序列的方法, 发现和网上都不一样. 我们从每个点出发向其后面第一个a, b, c, d ...连一条边,那么总的不同 ...
- codeforces 645E . Intellectual Inquiry
题目链接 如果不考虑重复的元素, 那么我们可以很容易的发现, 长度为n的字符串它的子串数量是 $ 2^n $ . 我们设每个到位置i, 答案的数量为f[i]. 然后我们考虑重复的, 我们发现, 每加入 ...
- CF CROC 2016 Intellectual Inquiry
题目链接:http://codeforces.com/contest/655/problem/E 大意是Bessie只会英文字母表中的前k种字母,现在有一个长度为m+n的字母序列,Bessie已经知道 ...
- codeforces 645 D. Robot Rapping Results Report 二分+拓扑排序
题目链接 我们可以发现, 这是一个很明显的二分+拓扑排序.... 如何判断根据当前的点, 是否能构造出来一个唯一的拓扑序列呢. 如果有的点没有出现, 那么一定不满足. 如果在加进队列的时候, 同时加了 ...
- CodeForces - 645 C.Enduring Exodus
快乐二分 用前缀和随便搞一下 #include <cstdio> using namespace std; ; int p[N]; ; inline int msum(int a, int ...
- 「CF645E」 Intellectual Inquiry
题目链接 CF645E 题意 有一个长为\(n\)的由小写字母组成的字符串,需要用小写字母再填\(m\)位,使最后的字符串中本质不同的子串数量尽量多,答案对\(10^9+7\)取模. 本题数据:\(n ...
- 05.24 ICPC 2019-2020 North-Western Russia Regional Contest复现赛+Codeforces Round #645 (Div. 2)
A.Accurate Movement(复现赛) 题意:两个木块最左边都在0的位置,最右边分别为a,b(b>a),并且短的木条只能在长木条内移动,问两个木条需要移动多少次才能使两个木条的右端都在 ...
随机推荐
- codewars 随手记
1.ES6数组遍历语法糖=> 在C#Linq里曾经用过,因此也不是很陌生. var range = Array.apply(null, Array(x)).map((_, i) => ++ ...
- Java EE 编程中路径
版权声明:未经博主允许,不得转载 首先我们要限定一个范围,是一个项目,或是以个访问地址..就先以一个项目为限定的范围 前述: 学过物理学的都知道相对运动和绝对运动, 虽然是相似的概念,但这里的要简单得 ...
- ubuntu 14.04安装右键打开终端功能
命令行运行,安装完成后需重启: sudo apt-get install nautilus-open-terminal
- Node调用C++(dll)
最近开始搞毕设了,打算用自己拿手的js来搞,但是仿佛入坑了,Node还不是很熟.总之,兵来将挡,水来土掩嘛,带着问题学习才是最高效的. 折腾1:Node 调用 C++ 刚开始,虽然我老师把dll文件给 ...
- javascript下ie7,ie8的Date Bug的解决
ie9+, chrome firefox opera下 string到Date 使用 new Date("2013-01-01"); 都是ok的. 但在ie7, ie8下 返回N ...
- STM3210x建工程库函数版本
1.首先下载一个固件库,我下载的是stm32f10x_stdperiph_lib 3.5V版的 2.新建一个文件夹,可命名为"STM32建工程库函数版本" 3.在"STM ...
- 带日期的bean转为json(bean->JSON)
示例代码: JsonBean bean = new JsonBean();bean.setName("NewBaby");bean.setAge(1);bean.setBorn(n ...
- codeforces Simple Molecules
link:http://codeforces.com/contest/344/problem/B 刚开始想复杂了.一开始就想当然地以为可以有多个点,其实,人家题目要求只有3个点啊! 然后题目就简单了. ...
- JDBC的应用实例
首先要添加一个引用的库 在项目上右键--构建路径--配置构建路径--在(库)中选择添加外部JAR--选择jar包添加 jar文件是驱动包 添加后包资源管理器中显示一个引用的库会有jar包 加载数据访问 ...
- UVa 673 平衡的括号
题意:给出包含"()"和"[]"的括号序列,判断是否合法. 用栈来完成,注意空串就行. #include<iostream> #include< ...