Codeforces Round #210 (Div. 1) problem C Levko and Strings

http://codeforces.com/contest/360/problem/C

極好的一道動態規劃, 給定一個小寫字母的字符串 S, 求其相同長度的串T,T中恰包含K個子串字典序大於S中相同位置的子串,求T有幾種,記 DP[ i ] [ j ][ 0或1 ] 爲 第i個位置爲止已有J個子串字典序大於S中相對應爲止的子串,最後一維表示相同與否,我在這裏用0表示相同,及T[i]=s[i],否則T[i]!=s[i]   我固定位置i, 向前遍歷 當到達位置t時, 令 (S[t] = T[t] ,S[t+1] = T[t+1]) S[i] 與T[i] 的關係分別討論。此時

若T[i]>S[i], t 每向前移動一位 , 滿足條件的子串就增加 n-i+1 個,我們若枚舉 j,則只需枚舉 j/(n-i+1) 次,整體複雜度爲n*n*log(n)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#include<cstring>
#include<vector>
#include<bitset>
#include<iterator>
#include<list>
#include<map>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
#define L p->ch[0]
#define R p->ch[1]
#define KeyTree root->ch[1]->ch[0]
typedef long long LL;
typedef pair<char, int> PII;
typedef vector<int> VI;
const int maxn = 2111;
const int INF = 1 << 30;
const int mod = (int) (1e9 + 7);
const LL X = 123;
template<typename T>
T gcd(T a, T b) {
	return b ? gcd(b, a % b) : a;
}
LL dp[maxn][maxn][2];
char s[maxn];
int ch[maxn];
LL P[maxn];
int main() {
	ios::sync_with_stdio(false);
	int n, k, i, j, t, r;
	cin >> n >> k;
	cin >> (s + 1);
	dp[0][0][1] = 1;
	dp[0][0][0] = 0;
	P[0] = 1;
	for (i = 1; i <= n; ++i) {
		ch[i] = (s[i] ^ 0x60);
	}
	r = n;
	for (i = 1, r = n; i <= n; ++i, --r) {
		for (j = 0; j <= k; ++j) {
			dp[i][j][0] = dp[i][j][1] = dp[i - 1][j][0] + dp[i - 1][j][1];
			LL& tv = dp[i][j][1];
			tv = dp[i][j][1] * (ch[i] - 1) % mod;
			for (t = i - 1; t >= 0 && j - (i - t) * r >= 0; --t) {
				tv += (dp[t][j - (i - t) * r][1]) * (26 - ch[i]);
			}
			tv %= mod;
		}
	}
	LL ans = (dp[n][k][0] + dp[n][k][1]) % mod;
	cout << ans << endl;
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章