zoukankan      html  css  js  c++  java
  • [CodeForces-759D]Bacterial Melee

    题目大意:
      有一串n个字母,每个位置的字母可以同化边上的一个字母,
      比如:ab可以变成aa或者bb。
      相对的两个同化不能同时发生,比如ab不能变成ba。
      现在给你一个字符串,问你经过任意次数的同化过程,最多能生成多少个字符串。

    思路:
      考虑同化过后的字符串与同化前的字符串的关系。
      如果我们把一个字符串中相邻且相同的字母缩在一起,那么我们可以发现每一次同化就相当于从原串中去掉了一个字符。
      这也就意味着同化过后的串一定是原串的一个子序列。
      同样,如果一个串是原串的一个子序列,它一定能由原串同化而来。
      我们可以先统计一下原串不同长度子序列的个数。
      对于一个长度为l的子序列,它里面有n-l个字符被缩过,那么缩之前的串总共有C(n,l)种可能。
      不同的子序列数量可以用DP求出来。
      f[i][j]表示以字符j结尾的长度为i的子序列数量,则f[i][j]=sum{f[i-1][k]|k≠j}+1,枚举i,j,k,时间复杂度O(n^2*26)。
      如果直接枚举k会TLE,只能过11个点,我们可以考虑用sum[i]记录长度为i的子串的数量和。
      由于结尾位置的字符已确定,所以组合数用C(n-1,l-1)算,时间复杂度O(n^2)。

     1 #include<cstdio>
     2 #include<cctype>
     3 typedef long long int64;
     4 inline int getint() {
     5     register char ch;
     6     while(!isdigit(ch=getchar()));
     7     register int x=ch^'0';
     8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     9     return x; 
    10 }
    11 const int N=5001,SIGMA=27,mod=1e9+7;
    12 char s[N];
    13 int f[N][SIGMA],sum[N],fact[N],factinv[N];
    14 inline int idx(const char &ch) {
    15     return ch-'a'+1;
    16 }
    17 void exgcd(const int &a,const int &b,int &x,int &y) {
    18     if(!b) {
    19         x=1;
    20         y=0;
    21         return;
    22     }
    23     exgcd(b,a%b,y,x);
    24     y-=a/b*x;
    25 }
    26 inline int inv(const int &x) {
    27     int ret,tmp;
    28     exgcd(x,mod,ret,tmp);
    29     return (ret%mod+mod)%mod;
    30 }
    31 inline int C(const int &n,const int &m) {
    32     return (int64)fact[n]*factinv[n-m]%mod*factinv[m]%mod;
    33 }
    34 int main() {
    35     const int n=getint();
    36     scanf("%s",s);
    37     fact[0]=factinv[0]=1;
    38     for(register int i=1;i<n;i++) {
    39         fact[i]=(int64)fact[i-1]*i%mod;
    40         factinv[i]=inv(fact[i]);
    41     }
    42     sum[0]=1;
    43     for(register int i=0;i<n;i++) {
    44         const int ch=idx(s[i]);
    45         for(register int i=1;i<=n;i++) {
    46             sum[i]=(sum[i]-f[i][ch]+mod)%mod;
    47             f[i][ch]=(sum[i-1]-f[i-1][ch]+mod)%mod;
    48             sum[i]=(sum[i]+f[i][ch])%mod;
    49         }
    50     }
    51     int ans=0;
    52     for(register int i=1;i<=n;i++) {
    53         ans=(ans+(int64)C(n-1,i-1)*sum[i]%mod)%mod;
    54     }
    55     printf("%d
    ",ans);
    56     return 0;
    57 }
  • 相关阅读:
    【QTP小技巧】02_QTP中Complete Word 实现(转载)
    【QTP专题】04_对象及操作方法
    【QTP专题】03_Add-in Manager插件
    【QTP专题】02_时间同步点问题
    loadrunner 11问题汇总
    system idle process
    html div四边阴影效果
    通过CSS实现 文字渐变色 的两种方式
    UIgradients – 美丽的UI渐变色分享站 并可转成CSS代码
    display:inline-block带来的问题及解决办法
  • 原文地址:https://www.cnblogs.com/skylee03/p/7809049.html
Copyright © 2011-2022 走看看