zoukankan      html  css  js  c++  java
  • Codeforces 360C DP 计算贡献

    题意:给你一个长度为n的字符串,定义两个字符串的相关度为两个串对应的子串中第一个串字典序大于第二个串的个数。现在给你相关度,和第二个串,问满足条件的第一个串有多少个?

    思路:设dp[i][j]为填了前i个字符,后面的字符和s相同,相关度为j的方案数。现在有两种转移:

    1:i位置填的字符大于s[i], 那么我们假设i前面第一个与s不相等的位置是l(即s[l + 1]到s[i]是相等的), 那么相当于左端点在[l + 1, i], 右端点在[i, n]的区间都会产生贡x献,那么从dp[l][j - (n - i + 1) * (i - l)]转移过来(把后面的贡献去掉,就是dp[l][j - (n - i + 1) * (i - l)]),dp[i][j] += ('z' - s[i]) * (dp[l][j - (n - i + 1) * (i - l)]);

    2:i位置填的数字小于等于s[i], 那么后面就没影响了,前面所有的l都可以转移:dp[i][j] += sum[j] * (s[i] - 'a), sum[j] 为dp[0][j]到dp[i - 1][j]的和。

    代码:

    #include <bits/stdc++.h>
    #define LL long long
    #define INF 0x3f3f3f3f
    #define db double
    #define pii pair<int, int>  
    using namespace std;
    const int maxn = 2010;
    const LL mod = 1000000007;
    LL dp[maxn][maxn], sum[maxn];
    char s[maxn];
    int main() {
    	int n, k;
    	scanf("%d%d", &n, &k);
    	scanf("%s", s + 1);
    	dp[0][0] = 1;
    	sum[0] = 1;
    	for (int i = 1; i <= n; i++) {
    		for (int j = 0; j <= k; j++) {
    			for (int l = i - 1; l >= 0 && j - (n - i + 1) * (i - l) >= 0; l--) {
    				dp[i][j] = (dp[i][j] + ((LL)('z' - s[i]) * dp[l][j - (n - i + 1) * (i - l)]) % mod) % mod;
    			}
    			dp[i][j] = (dp[i][j] + ((LL)(s[i] - 'a') * sum[j]) % mod) % mod;
    			sum[j] = (sum[j] + dp[i][j]) % mod;
    		}
    	}
    	LL ans = 0;
    	for (int i = 0; i <= n; i++) {
    		ans = (ans + dp[i][k]) % mod;	
    	}
    	printf("%lld
    ", ans);
    }
    

      

  • 相关阅读:
    vuex状态管理demo
    vuex与redux,我们都一样
    vue-quill-editor + element-ui upload实现富文本图片上传
    总结移动端页面开发时需要注意的一些问题
    laravel 运行出错RuntimeException No application encryption key has been specified.
    JS 正则匹配 只匹配汉字
    LINUX统计一个文件中特定字符串出现的次数
    Nginx Log日志统计分析常用命令
    python之mysqldb模块安装
    PHP 可变参数 ( ... ) 和参数解包
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/11123937.html
Copyright © 2011-2022 走看看