CodeForces - 361E Levko and Strings
Posted 蒟蒻JHY
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - 361E Levko and Strings相关的知识,希望对你有一定的参考价值。
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 i, j (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
2 2
yz
26
2 3
yx
2
4 7
abcd
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的主要内容,如果未能解决你的问题,请参考以下文章