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\n",f[1][k]);
return 0;
}

  

 

CodeForces - 361E Levko and Strings的更多相关文章

  1. Codeforces 360C Levko and Strings dp

    题目链接:点击打开链接 题意: 给定长度为n的字符串s,常数k 显然s的子串一共同拥有 n(n-1)/2 个 要求找到一个长度为n的字符串t,使得t相应位置的k个子串字典序>s #include ...

  2. Codeforces 385B Bear and Strings

    题目链接:Codeforces 385B Bear and Strings 记录下每一个bear的起始位置和终止位置,然后扫一遍记录下来的结构体数组,过程中用一个变量记录上一个扫过的位置,用来去重. ...

  3. Codeforces 482C Game with Strings(dp+概率)

    题目链接:Codeforces 482C Game with Strings 题目大意:给定N个字符串,如今从中选定一个字符串为答案串,你不知道答案串是哪个.可是能够通过询问来确定, 每次询问一个位置 ...

  4. 【24.34%】【codeforces 560D】Equivalent Strings

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...

  5. codeforces B. Levko and Permutation 解题报告

    题目链接:http://codeforces.com/problemset/problem/361/B 题目意思:有n个数,这些数的范围是[1,n],并且每个数都是不相同的.你需要构造一个排列,使得这 ...

  6. CodeForces 682D Alyona and Strings (四维DP)

    Alyona and Strings 题目链接: http://acm.hust.edu.cn/vjudge/contest/121333#problem/D Description After re ...

  7. codeforces 518A. Vitaly and Strings

    A. Vitaly and Strings time limit per test 1 second memory limit per test 256 megabytes input standar ...

  8. Codeforces 149 E. Martian Strings

    正反两遍扩展KMP,维护公共长度为L时.出如今最左边和最右边的位置. . .. 然后枚举推断... E. Martian Strings time limit per test 2 seconds m ...

  9. Codeforces 985 F - Isomorphic Strings

    F - Isomorphic Strings 思路:字符串hash 对于每一个字母单独hash 对于一段区间,求出每个字母的hash值,然后排序,如果能匹配上,就说明在这段区间存在字母间的一一映射 代 ...

随机推荐

  1. #3 working with data stored in files && securing your application (PART II)

    Security problems is more and more important on the internet today. You can see the problems . This ...

  2. Three Steps to Migrate Group Policy Between Active Directory Domains or Forests Using PowerShell

    Three Steps Ahead Have you ever wished that you had three legs? Imagine how much faster you could ru ...

  3. Spring MVC学习总结

    Spring MVC学习总结 Spring MVC学习路(一) 下载配置文件 Spring MVC学习路(二) 设置配置文件 Spring MVC学习路(三) 编写第一个demo Spring MVC ...

  4. Spring Boot 学习系列(03)—jar or war,做出你的选择

    此文已由作者易国强授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 两种打包方式 采用Spring Boot框架来构建项目,我们对项目的打包有两种方式可供选择,一种仍保持原有的 ...

  5. Google Optimize 安装使用教程

    Google Optimize 介绍 打开链接 https://optimize.google.com/optimize/signup/ 填入电邮地址后等待注册邀请 Google Optimize是什 ...

  6. PHP PDO fetch() 详解

    环境:(PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0) PDOStatement::fetch — 从结果集中获取下一行 说明 PDOStatement ...

  7. 06 JVM 是如何处理异常的

    在 JAVA 中,异常处理的方式主要是抛出异常和捕获异常.这两大要素共同实现程序控制流的非正常转移. 抛出异常可以分为显示和隐式两种.显示抛出异常的主体是应用程序,它指的是在程序中使用 throw 关 ...

  8. [错误处理]AttributeError: 'generator' object has no attribute 'next'

    在python3下学习yield用法. 程序如下: def bar(n): m = n while True: m += 1 yield m b = bar(3) print(b.next()) 程序 ...

  9. java I/O类 File使用

    11.3 I/O类使用 由于在IO操作中,需要使用的数据源有很多,作为一个IO技术的初学者,从读写文件开始学习IO技术是一个比较好的选择.因为文件是一种常见的数据源,而且读写文件也是程序员进行IO编程 ...

  10. 抄书 Richard P. Stanley Enumerative Combinatorics Chapter 2 Sieve Methods

    2.1 Inclusion-Exclusion Roughly speaking, a "sieve method" in enumerative combinatorics is ...