CF CROC 2016 Intellectual Inquiry
2016-05-06 14:54
591 查看
题目链接:http://codeforces.com/contest/655/problem/E
大意是Bessie只会英文字母表中的前k种字母,现在有一个长度为m+n的字母序列,Bessie已经知道了前m个字符,问如何填充剩下的n个字符,使得整个序列的不同子序列数目最大。当然所有字母都得是Bessie会的前k个字母。
两个月前比赛的时候做的,是一道不错的题。
关于子序列个数的计算
令dp[i]表示前i个数字组成的序列中子序列的个数,
则对于第i个数字a[i]来说,dp[i]来源于两种情况的转化:
序列中前一个数字为a[i],记这种情况为s1以及前一个数字不为a[i],计这种情况为s2。
dp[i]=s1+s2*2=2*dp[i-1]-s1
可以这么理解,首先之前的子序列个数是dp[i-1],这些子序列直接都加一个a[i],一定是可以的。这只是新答案中以a[i]为结尾的情况,那么不以a[i]为结尾的情况,直接就是继承自原来的s2。
所以可以看出要使得dp值尽量大,就要让每一次因为重复需要减去的s1值尽可能小,也就是要让a[i]距离上一次出现a[i]尽可能地远。
根据前m个字符信息,计算可以使用的k个字母的最后出现的位置,根据这个来进行排序,使得最后出现的位置越小的字母排在越前面。
对于剩下的n个需要填充的字符,直接按照排出来的k个字母顺序,循环使用。
最后按照上述子序列计算方式来进行计算。
View Code
大意是Bessie只会英文字母表中的前k种字母,现在有一个长度为m+n的字母序列,Bessie已经知道了前m个字符,问如何填充剩下的n个字符,使得整个序列的不同子序列数目最大。当然所有字母都得是Bessie会的前k个字母。
两个月前比赛的时候做的,是一道不错的题。
关于子序列个数的计算
令dp[i]表示前i个数字组成的序列中子序列的个数,
则对于第i个数字a[i]来说,dp[i]来源于两种情况的转化:
序列中前一个数字为a[i],记这种情况为s1以及前一个数字不为a[i],计这种情况为s2。
dp[i]=s1+s2*2=2*dp[i-1]-s1
可以这么理解,首先之前的子序列个数是dp[i-1],这些子序列直接都加一个a[i],一定是可以的。这只是新答案中以a[i]为结尾的情况,那么不以a[i]为结尾的情况,直接就是继承自原来的s2。
所以可以看出要使得dp值尽量大,就要让每一次因为重复需要减去的s1值尽可能小,也就是要让a[i]距离上一次出现a[i]尽可能地远。
根据前m个字符信息,计算可以使用的k个字母的最后出现的位置,根据这个来进行排序,使得最后出现的位置越小的字母排在越前面。
对于剩下的n个需要填充的字符,直接按照排出来的k个字母顺序,循环使用。
最后按照上述子序列计算方式来进行计算。
#include <iostream> #include <vector> #include <algorithm> #include <string> #include <string.h> #include <stdio.h> #include <math.h> #include <queue> #include <stack> #include <map> #include <set> using namespace std; const int N=2234567; const long long MOD=1e9+7; char s ; struct Node { char ch; int pos; Node(){ pos=-1; } bool operator < (const Node &o) const { return pos<o.pos; } }node[30]; long long cnt[30]; int main() { for (int i=0;i<26;i++) node[i].ch=char('a'+i); int n,k; scanf("%d %d",&n,&k); scanf("%s",s); int m=strlen(s); for (int i=0;i<m;i++) { int id=s[i]-'a'; node[id].pos=i; } sort(node,node+k); for (int i=m,cnt=0;i<m+n;i++,cnt++) { if (cnt>=k) cnt=0; s[i]=node[cnt].ch; } s[m+n]=0; //puts(s); long long ret=1; memset(cnt,0,sizeof cnt); for (int i=0;i<m+n;i++) { long long tmp=ret; int id=s[i]-'a'; ret=ret*2-cnt[id]; ret+=MOD; ret%=MOD; while (ret<0) ret+=MOD; cnt[id]=tmp; } printf("%I64d\n",ret); return 0; }
View Code
相关文章推荐
- easyUi 无限极分类
- ios上 更改 状态栏(UIStatusBar)的颜色
- jpa,querydsl
- ajax request VS normal request
- Android字符串相关类 - CharSequence
- Android字符串相关类 - CharSequence
- java.lang.IllegalArgumentException: id to load is required for loading
- iOS UICollectionView XIB
- iOS开发-UITextField 使用全面解析
- QML UI布局
- 用结点实现链表LinkedList,用数组和结点实现栈Stack,用数组和结点链表实现队列Queue
- cannot convert value of type cbbf 'String!' to expected argument type 'inout String'
- Java druid的使用
- Backpropagation, Intuitions
- NSOperationqueue
- H5开发01——mui.fire()触发自定义事件
- UIMenuController使用
- rpmbuild的一个小常识
- java中BlockingQueue 的使用
- [codeforces]#350E. Correct Bracket Sequence Editor