CodeForces 660E Different Subsets For All Tuples(动态规划)

题意:给出一个有m个字符组成的所有长度为n的字符串的集合,现在问每个字符串的不同子串之和是多少。

思路:

首先用dp[I]表示长度为n的所有字符串的子串数量,假设当前已经处理了长度为i1的字符串集合,现在要处理长度为I的字符串集合

考虑在长度为I-1的字符串集合的每一个字符串后面加一个字符

那么数量增加了dp[I-1]-dp[lastpos-1],lastpos是当前字符出现的最后一个位置

比如当前lastpos的位置是j,那么这时候就要减去(m-1)^(I-1-j)*dp[j-1],然后维护一个前缀和就可以了。

#include
#define eps 1e-6
#define LL long long
#define pii pair
#define pb push_back
#define mp make_pair
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

const int MAXN = 1e6+7;
const int MOD = 1e9+7;
int n, m;
LL sumv[MAXN];
LL dp[MAXN];
// LL pow_mod(int a, int b) {
// 	if (!b) return 1;
// 	LL ans = pow_mod(a, b/2);
// 	ans = ans*ans % MOD;
// 	if (b&1) ans = ans * a % MOD;
// 	return ans;
// }
int main()
{
    //freopen("input.txt", "r", stdin);
	scanf("%d%d", &n, &m); 
	dp[0] = 1;
	for (int i = 1; i <= n; i++) {
		dp[i] = m * (dp[i-1]*2 - sumv[i-1]) % MOD;
		sumv[i] = (sumv[i-1]*(m-1) + dp[i-1]) % MOD;
		//cout << dp[i] << endl;
	}
	dp[n] = (dp[n]+MOD) % MOD;
	cout << dp[n] << endl;
    return 0;
}
















你可能感兴趣的:(程序设计竞赛,codeforces,动态规划)