• CodeForces


    Discription

    Levko loves strings of length n, consisting of lowercase English letters, very much. He has one such string s. For each string t of length n, Levko defines its beauty relative to s as the number of pairs of indexes ij (1 ≤ i ≤ j ≤ n), such that substring t[i..j] is lexicographically larger than substring s[i..j].

    The boy wondered how many strings t are there, such that their beauty relative to sequals exactly k. Help him, find the remainder after division this number by1000000007 (109 + 7).

    A substring s[i..j] of string s = s1s2... sn is string sisi  +  1... sj.

    String x  =  x1x2... xp is lexicographically larger than string y  =  y1y2... yp, if there is such number r (r < p), that x1  =  y1,  x2  =  y2,  ... ,  xr  =  yr and xr  +  1 > yr  +  1. The string characters are compared by their ASCII codes.

    Input

    The first line contains two integers n and k (1 ≤ n ≤ 2000, 0 ≤ k ≤ 2000).

    The second line contains a non-empty string s of length n. String s consists only of lowercase English letters.

    Output

    Print a single number — the answer to the problem modulo 1000000007 (109 + 7).

    Examples

    Input
    2 2
    yz
    Output
    26
    Input
    2 3
    yx
    Output
    2
    Input
    4 7
    abcd
    Output
    21962


    不难想到设状态 f[i][j] 表示:已经考虑了第i位往后的字符,并且此时有j对 T 字典序严格大于 S的区间的方案数。
    根据设定的状态,我们可以直接得出一个 O(N^3) 的转移:
    当我们要计算 f[i][?] 的时候,我们先枚举第二维是多少,然后再枚举T[i~n]与S[i~n]第一个不一样的字符对 T[k]&&S[k] 在哪里,然后算贡献。
    也就是 f[i][j] = ∑ (s[k] - 1) * f[k+1][j] + ∑ (26 - s[k]) * f[k+1][j- (n-k+1) * (k-i+1)]. (i<=k<=n)

    现在来考虑一下怎么优化这个dp。
    第一个∑比较好优化,直接用一个 g[j] 记录 (s[k] - 1) * f[k+1][j] 这个后缀和就好了。
    第二个∑看起来好复杂啊。。。。这该咋优化。

    考虑我们枚举i的时候,i和n都是固定的,所以 (n-k+1) * (k-i+1) 此时就是一个关于 k 的开口向下的二次函数,发现k靠近i或者靠近n的时候,这个函数值不是很大,而当k趋近于 (n+i)/2 的时候,这个函数值很大,很可能没法转移。
    这告诉我们什么?
    第二种转移的实际路径其实特别少,并且都是 一个 前缀 + 一个 后缀 (对于k来说)的形式,所以我们只需要当j增加的时候记录 前缀右端点 和 后缀左端点的移动,然后直接暴力转移即可。

    那么怎么证明这个函数的转移路径真的很少呢?
    我们来列一下式子,实际的转移路径总数 = ∑ ∑ ∑ [(n+2-i-j)*j <= k]
    可以抽象成 二次函数 y=x(1-x) ,y=x(2-x) ...,y=x(n+2-x) 在 y=1,y=2....y=k直线 下的整点数量和,可以发现的确是很少的hhhh(谁让我也不会具体证明啦)

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=2005,ha=1e9+7;
    inline void add(int &x,int y){ x+=y; if(x>=ha) x-=ha;}
    inline int ADD(int x,int y){ x+=y; return x>=ha?x-ha:x;}
    int f[maxn][maxn],n,m,g[maxn],k,ans=0;
    char s[maxn];
    
    inline void solve(){
    	f[n+1][0]=1;
    	for(int i=n;i;i--){
    		for(int j=0;j<=k;j++) add(g[j],f[i+1][j]*(ll)(s[i]-'a')%ha);
    		
    		int L=i-1,R=n+1;
    		for(int j=0;j<=k;j++){
    			while(j>=(n-L)*(L+2-i)&&L+1<R) L++;
    			while(j>=(n-R+2)*(R-i)&&L+1<R) R--;
    			for(int l=i;l<=L;l++) add(f[i][j],('z'-s[l])*(ll)f[l+1][j-(n-l+1)*(l-i+1)]%ha);
    			for(int l=n;l>=R;l--) add(f[i][j],('z'-s[l])*(ll)f[l+1][j-(n-l+1)*(l-i+1)]%ha);
    			add(f[i][j],g[j]);
    		}
    		
    		add(f[i][0],1);
    	}
    }
    
    int main(){
    	scanf("%d%d",&n,&k);
    	scanf("%s",s+1);
    	solve();
    	printf("%d
    ",f[1][k]);
    	return 0;
    }
    
    
    

      

     
    
    
  • 相关阅读:
    zookeeper分布式锁
    zookeeper集群,每个服务器上的数据是相同的,每一个服务器均可以对外提供读和写的服务,这点和redis是相同的,即对客户端来讲每个服务器都是平等的。
    理解分布式系统
    zookeeper
    Codeforces Round #261 (Div. 2)[ABCDE]
    L脚本语言语法手冊 0.10版
    [Lua]mac 上安装lua
    extjs 按条件查询出的数据在grid上不显示
    木桶效应
    Shuttle ESB(四)——公布订阅模式实例介绍(1)
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8984831.html
Copyright © 2020-2023  润新知