zoukankan      html  css  js  c++  java
  • [hdu5396 Expression]区间DP

    题意:给一个表达式,求所有的计算顺序产生的结果总和

    思路:比较明显的区间dp,令dp[l][r]为闭区间[l,r]的所有可能的结果和,考虑最后一个符号的位置k,k必须在l,r之间,则l≤k<r,dp[l][r]=Σ{dp[l][k]?dp[k+1][r]}*(r-l-1)!/[(k-l)!(r-k-1)!],其中(r-l-1)!/[(k-l)!(r-k-1)!]表示从左区间和右区间选择符号的不同方法总数(把左右区间看成整体,那么符号的选择在整体间也有顺序,内部的顺序不用管,那是子问题需要考虑的),相当于(k-l)个0和(r-k-1)个1放一起的不同排列方法总数。

    对花括号里面的'?'分为三种情况:

    1. '+'  假设左区间有x种可能的方法,右区间有y种可能的方法,由于分配律的存在,左边的所有结果和会重复计算y次,右边的所有结果和会重复计算x次,而左边共(k-l)个符号,右边共(r-k-1)个符号,所以合并后的答案dp[l][r]=dp[l][k]*(r-k-1)!+dp[k+1][r]*(k-l)!
    2. '-'   与'+'类似
    3. '*'   由分配律,合并后的答案dp[l][r]=dp[l][k]*dp[k+1][r]
    #pragma comment(linker, "/STACK:10240000")
    #include <map>
    #include <set>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define X                   first
    #define Y                   second
    #define pb                  push_back
    #define mp                  make_pair
    #define all(a)              (a).begin(), (a).end()
    #define fillchar(a, x)      memset(a, x, sizeof(a))
    #define copy(a, b)          memcpy(a, b, sizeof(a))
    
    typedef long long ll;
    typedef pair<int, int> pii;
    typedef unsigned long long ull;
    
    //#ifndef ONLINE_JUDGE
    void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
    void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
    void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
    while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
    void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
    void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
    void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
    //#endif
    template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
    template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}
    
    const double PI = acos(-1.0);
    const int INF = 1e9 + 7;
    const double EPS = 1e-12;
    
    /* -------------------------------------------------------------------------------- */
    
    template<int mod>
    struct ModInt {
        const static int MD = mod;
        int x;
        ModInt(ll x = 0): x(x % MD) {}
        int get() { return x; }
    
        ModInt operator + (const ModInt &that) const { int x0 = x + that.x; return ModInt(x0 < MD? x0 : x0 - MD); }
        ModInt operator - (const ModInt &that) const { int x0 = x - that.x; return ModInt(x0 < MD? x0 + MD : x0); }
        ModInt operator * (const ModInt &that) const { return ModInt((long long)x * that.x % MD); }
        ModInt operator / (const ModInt &that) const { return *this * that.inverse(); }
    
        ModInt operator += (const ModInt &that) { x += that.x; if (x >= MD) x -= MD; }
        ModInt operator -= (const ModInt &that) { x -= that.x; if (x < 0) x += MD; }
        ModInt operator *= (const ModInt &that) { x = (long long)x * that.x % MD; }
        ModInt operator /= (const ModInt &that) { *this = *this / that; }
    
        ModInt inverse() const {
            int a = x, b = MD, u = 1, v = 0;
            while(b) {
                int t = a / b;
                a -= t * b; std::swap(a, b);
                u -= t * v; std::swap(u, v);
            }
            if(u < 0) u += MD;
            return u;
        }
    
    };
    typedef ModInt<1000000007> mint;
    
    const int maxn = 1e2 + 7;
    const int md = 1e9 + 7;
    mint dp[maxn][maxn], fac[maxn], facinv[maxn];
    int a[maxn];
    char s[maxn];
    
    mint get(mint a, char ch, mint b, mint ca, mint cb) {
        if (ch == '+') return a * cb + b * ca;
        if (ch == '-') return a * cb - b * ca;
        if (ch == '*') return a * b;
    }
    
    void init() {
        fac[0] = facinv[0] = 1;
        for (int i = 1; i < maxn; i ++) fac[i] = fac[i - 1] * i;
        for (int i = 1; i < maxn; i ++) facinv[i] = facinv[i - 1] / i;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
    #endif // ONLINE_JUDGE
        int n;
        init();
        while (cin >> n) {
            for (int i = 1; i <= n; i ++) {
                scanf("%d", a + i);
            }
            scanf("%s", s);
            fillchar(dp, 0);
            for (int i = 1; i <= n; i ++) dp[i][i] = a[i];
            for (int L = 2; L <= n; L ++) {
                for (int i = 1; i + L - 1 <= n; i ++) {
                    int j = i + L - 1;
                    for (int k = i; k < j; k ++) {
                        dp[i][j] += get(dp[i][k], s[k - 1], dp[k + 1][j], fac[k - i], fac[j - k - 1]) * fac[j - i - 1] * facinv[k - i] * facinv[j - k - 1];
                    }
                }
            }
            printf("%d
    ", dp[1][n].get());
        }
        return 0;
    }
    
  • 相关阅读:
    使用 Spring data redis 结合 Spring cache 缓存数据配置
    Spring Web Flow 笔记
    Linux 定时实行一次任务命令
    css js 优化工具
    arch Failed to load module "intel"
    go 冒泡排序
    go (break goto continue)
    VirtualBox,Kernel driver not installed (rc=-1908)
    go运算符
    go iota
  • 原文地址:https://www.cnblogs.com/jklongint/p/4740849.html
Copyright © 2011-2022 走看看