zoukankan      html  css  js  c++  java
  • HDU5396——区间DP+排列组合——Expression

    http://acm.hdu.edu.cn/showproblem.php?pid=5396

    /*
    题目大意:给你一些表达式,问你不考虑乘除优先级,问所有可能性之和为多少
    比方说 (1+2)+3  1+(2+3)  算不同
    定义dp[i][j] 表示从i到j之和
    令k为两个表达式之间的符号
    如果k为*  状态转移方程
    dp[i][j] = (dp[i][j] + dp[i][k]*dp[k+1][j])
    两者情况之积  (1+2*3)*(2+3+4) 左边有两种,右边有两种,那么就是四,因为×肯定是最后一步做的
    如果k为+/- 状态转移方程
    dp[i][j] = (dp[i][j] + dp[i][k]*(j-k-1) + dp[k+1][j]*(k-i))
    和的话    (1+2*3) + (2+3+4) 加是最后一步做的,左边的数会加(j-k-1)!次,即右边的全排列的随时可以加,后面同理
    最后都要乘以一个组合数comb[j-i-1][k-i]的原因:
    假设我左边两个符号是 + * 右边是 + +
    在已经确定了什么必须与什么相乘情况下,只能是选左或者选右
    就是 (1+2*3)*(2+3+4) 我们假设顺序必须是2*3 然后 1+(2*3) 右边是(2+3)然后(2+3)+4,但是我们2*3之后可以选择右边(2+3)而不选择1+(2*3)那么这些排列情况需要考虑
    我们已经知道了左边的乘法必须先于+法,右边的第一个加法先于第二个加法
    那么可以看成一共有4个位置我要选择两个位置把第一个放进去并且满足,那第二个是不是已经确定了
    ----
    *+--
    *-+-
    *--+
    -*+-
    -*-+
    --*+
    6种
    */
    /************************************************
     * Author        :Powatr
     * Created Time  :2015-8-19 12:27:50
     * File Name     :HDU5396.cpp
     ************************************************/
    
    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <vector>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <list>
    #include <map>
    #include <set>
    #include <bitset>
    #include <cstdlib>
    #include <ctime>
    using namespace std;
    
    #define lson l, mid, rt << 1
    #define rson mid + 1, r, rt << 1 | 1
    typedef long long ll;
    const int MAXN = 1e2 + 10;
    const int INF = 0x3f3f3f3f;
    const int MOD = 1e9 + 7;
    
    ll comb[MAXN][MAXN];
    ll fac[MAXN];
    
    void inti()
    {
        for(int i = 0 ; i <= 100; i++){
            comb[i][0] = comb[i][i] = 1;
            for(int j = 1; j <= i; j++){
                comb[i][j] = (comb[i-1][j-1] + comb[i-1][j])%MOD;
            }
        }
        fac[0] = 1;
        for(int i = 1; i <= 100; i++){
            fac[i] = fac[i-1] * i % MOD;
        }
    }
    int main(){
        int n;
        char s[MAXN];
        int a[MAXN];
        ll dp[MAXN][MAXN];
        inti();
        while(~scanf("%d", &n)){
            for(int i = 1; i <= n; i++)
                scanf("%d", &a[i]);
            scanf("%s", s+1);
            for(int i = n ; i >= 1; i--){
                dp[i][i] = a[i];
                for(int j = i + 1; j <= n; j++){
                    dp[i][j] = 0;
                    for(int k = i; k <= j; k++){
                        if(s[k] == '*'){
                            dp[i][j] = (dp[i][j] + dp[i][k]*dp[k+1][j]%MOD*comb[j-i-1][k-i])%MOD;
                        }
                        else if(s[k] == '+'){
                            dp[i][j] = (dp[i][j] + (dp[i][k]*fac[j-k-1] + dp[k+1][j]*fac[k-i])%MOD*comb[j-i-1][k-i])%MOD;
                        }
                        else if(s[k] == '-'){
                            dp[i][j] = (dp[i][j] + (dp[i][k]*fac[j-k-1] - dp[k+1][j]*fac[k-i])%MOD*comb[j-i-1][k-i])%MOD;
                        }
                    }
                }
            }
            printf("%I64d
    ", (dp[1][n]+MOD)%MOD);
        }
        return 0;
    }
    

      

  • 相关阅读:
    【转】CentOS7安装iptables防火墙
    CentOS7使用firewalld打开关闭防火墙与端口
    CentOS7永久更改主机名
    CentOS7下安装GUI图形界面
    sql server2008 r2 密钥
    Response.Flush和Response.BufferOutput
    Asp.net使用JQuery实现评论的无刷新分页及分段延迟加载效果
    总结一下使用Emgucv的经验和经历
    c# 鼠标拖动缩放图片
    c# winfrom 在panel上绘制矩形
  • 原文地址:https://www.cnblogs.com/zero-begin/p/4741980.html
Copyright © 2011-2022 走看看