• CF CROC 2016 Intellectual Inquiry


    题目链接: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个字母顺序,循环使用。

    最后按照上述子序列计算方式来进行计算。

     1 #include <iostream>
     2 #include <vector>
     3 #include <algorithm>
     4 #include <string>
     5 #include <string.h>
     6 #include <stdio.h>
     7 #include <math.h>
     8 #include <queue>
     9 #include <stack>
    10 #include <map>
    11 #include <set>
    12 
    13 using namespace std;
    14 
    15 
    16 const int N=2234567;
    17 
    18 const long long MOD=1e9+7;
    19 
    20 char s[N];
    21 struct Node {
    22     char ch;
    23     int pos;
    24     Node(){
    25         pos=-1;
    26     }
    27     bool operator < (const Node &o) const {
    28         return pos<o.pos;
    29     }
    30 }node[30];
    31 long long cnt[30];
    32 int main() {
    33     for (int i=0;i<26;i++)
    34         node[i].ch=char('a'+i);
    35     int n,k;
    36     scanf("%d %d",&n,&k);
    37     scanf("%s",s);
    38     int m=strlen(s);
    39     for (int i=0;i<m;i++) {
    40         int id=s[i]-'a';
    41         node[id].pos=i;
    42     }
    43     sort(node,node+k);
    44     for (int i=m,cnt=0;i<m+n;i++,cnt++) {
    45         if (cnt>=k) cnt=0;
    46         s[i]=node[cnt].ch;
    47     }
    48     s[m+n]=0;
    49     //puts(s);
    50     long long ret=1;
    51     memset(cnt,0,sizeof cnt);
    52     for (int i=0;i<m+n;i++) {
    53         long long tmp=ret;
    54         int id=s[i]-'a';
    55         ret=ret*2-cnt[id];
    56         ret+=MOD;
    57         ret%=MOD;
    58         while (ret<0) ret+=MOD;
    59         cnt[id]=tmp;
    60     }
    61     printf("%I64d
    ",ret);
    62     return 0;
    63 }
    View Code
  • 相关阅读:
    Android 面试题(答案最全)
    Android Studio导入github下载的工程
    Android清除本地数据缓存代码
    内存缓存LruCache实现原理
    OD调试器调试Delphi程序按钮事件断点方法
    OllyDBG找到按钮的处理函数
    delphi中Record 和Packed Record的区别
    这些年,我们自己换的滤芯
    大众车机天宝187A Hack笔记
    Delphi中DLL的创建和使用
  • 原文地址:https://www.cnblogs.com/micrari/p/5465622.html
Copyright © 2020-2023  润新知