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;
}

  

 

最新文章

  1. Linux less 命令
  2. ntko office在线编辑控件问题记录
  3. js控制台输出console
  4. opencv5-objdetect之级联分类器
  5. 21. Clone Graph
  6. JS表单设置值
  7. HTML5 manifest离线缓存
  8. WPF 将PPT,Word转成图片
  9. C++设计模式——代理模式
  10. js 引用类型比较
  11. 代码之美——Doom3源代码赏析2
  12. DEDE中 field:rel 是什么意思,起一个什么样的作用效果
  13. DDGScreenShot—图片擦除功能
  14. 1.7 All components require plug-in?
  15. 【原创】大数据基础之ElasticSearch(5)重要配置及调优
  16. log4j的详细配置
  17. Annotations
  18. C语言第五讲,语句 顺序循环选择.
  19. Kubernetes中的亲和性与反亲和性
  20. Request实例

热门文章

  1. 如何使用DroidPlugin——DroidPlugin初体验
  2. HDU 3848 CC On The Tree 树形DP
  3. linux环境搭建系列之tomcat安装步骤
  4. python批量爬取文档
  5. Leetcode 567.字符串的排列
  6. 菜鸟之路——机器学习之KNN算法个人理解及Python实现
  7. CodeForces Round #498 Div.3 A. Adjacent Replacements
  8. 为不是函数的对象 'dbo.xxxx' 提供了参数。如果这些参数要作为表提示,则需要使用 WITH 关键字
  9. mysql 修改密码 开启远程访问权限
  10. 【bzoj1266】[AHOI2006]上学路线route 最短路+最小割