zoukankan      html  css  js  c++  java
  • hdu 4055 Number String

    题意:

    给出一个长度为n-1的字符串,字符串包含了'I','D','?',现在需要你按照字符串的要求构造排列,求方案数对1e9+7取模('I'的要求是前一个数要小于当前的数,'D'的要求是前一个数要大于当前的数,'?'的要求是前一个数随便放)

    题解:

    求方案数,首先会想到排列组合,然后会想到递推,这题很显然不能使用排列组合,考虑递推。

    现在的问题是定义状态和状态转移:

    首先考虑对于答案来定义状态,定义dp[i]表示1~i排列符合条件的数量,那么答案就是dp[n],但是可以发现的是这种状态没法转移因为不能满足当前某个字符的要求,所以应该再加一维dp[i][j]表示1~i的排列中最后一位数是j。

    现在考虑转移:

    如果当前字符串为'I' 那么dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j - 2] + ...... dp[i - 1][1]

    如果当前字符串为'D',但是会发现dp[i - 1][i]根本没有计算过,所以这样的转移不可行,但是我们会发现,当最后一位是j的时候,将1~i-1位置上的大于等于j的数,数值加1,依然会满足条件,那么dp[i][j] = dp[i - 1][j ] + dp[i - 1][j + 1] + ...... dp[i - 1][i -1],

    如果当前字符串为'?'那么dp[i][j] = dp[i - 1][1] + dp[i - 1][2] + ...... dp[i - 1][i - 1]

    然后前缀优化优化就可以搞了。。。

    代码:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    
    const int N = 1e3 + 7;
    const int mod = 1e9 + 7;
    char ch[N];
    int dp[N][N], sum[N];
    
    int main () {
    	scanf ("%s", ch + 1);
    	int n = strlen (ch + 1) + 1;
    	dp[1][1] = 1;
    	for (int i = 2; i <= n; ++i) {
    		for (int j = 1; j < i; ++j) 
    			sum[j] = (sum[j - 1] + dp[i - 1][j]) % mod;
    		for (int j = 1; j <= i; ++j) {
    			if (ch[i - 1] == 'I') dp[i][j] = sum[j - 1] % mod;
    			else if (ch[i - 1] == 'D') dp[i][j] = (sum[i  - 1] - sum[j - 1] + mod) % mod;
    			else dp[i][j] = sum[i - 1] % mod;
    		}
    	}
    	int ret = 0;
    	for (int i = 1; i <= n; ++i) ret = (ret + dp[n][i]) % mod;
    	cout << ret << endl;
    	return 0;
    }
    

      

    总结:

    排列计数一般都根据答案来定义,问排列的方案第一维一般是1~i的排列的方案数,第二维第三维根据条件来定义。。。(套路)~

  • 相关阅读:
    使用边缘计算来改变5G世界中的网络
    解开关于人工智能的六个迷思
    哪些数据将成为区块链系统的关键数据?
    如何通过7个步骤构建机器学习模型
    人工智能的发展体现了人类社会由实向虚的趋势
    5G技术与人工智能的智能结合
    量子计算总是混合的,这需要不断协调
    7.5省队集训 tree
    bzoj2989&4170: 数列
    bzoj1010: [HNOI2008]玩具装箱toy
  • 原文地址:https://www.cnblogs.com/xgtao/p/5986925.html
Copyright © 2011-2022 走看看