hdu 5396 区间dp+组合

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

Problem Description

Teacher Mai has n numbers a1,a2,?,anand n?1 operators("+",
"-" or "*")op1,op2,?,opn?1,
which are arranged in the form a1 op1 a2 op2 a3 ? an.

He wants to erase numbers one by one. In i-th
round, there are n+1?i numbers
remained. He can erase two adjacent numbers and the operator between them, and then put a new number (derived from this one operation) in this position. After n?1 rounds,
there is the only one number remained. The result of this sequence of operations is the last number remained.

He wants to know the sum of results of all different sequences of operations. Two sequences of operations are considered different if and only if in one round he chooses different numbers.

For example, a possible sequence of operations for "1+4?6?8?3"
is 1+4?6?8?3→1+4?(?2)?3→1+(?8)?3→(?7)?3→?21.

Input

There are multiple test cases.

For each test case, the first line contains one number n(2≤n≤100).

The second line contains n integers a1,a2,?,an(0≤ai≤109).

The third line contains a string with length n?1 consisting
"+","-" and "*", which represents the operator sequence.

Output

For each test case print the answer modulo 109+7.

Sample Input

3
3 2 1
-+
5
1 4 6 8 3
+*-*

Sample Output

2
999999689

Hint

 Two numbers are considered different when they are in different positions.
/**
hdu 5396  区间dp+组合
题目大意:给定一个只含有+-*的表达式,让你加括号决定运算顺序,问所有运算顺序可得的总和是多少?
解题思路:看一眼就知道区间dp最后差一个地方没有调出来,悲剧了,看了题解才知道左右区间还要乘上组合数==
           (转) 用dp[l][r]表示第l个数到第r个数组成的各种顺序的表达式和是多少,t[l][r]表示第l个数到第r
           个数有多少种不同的组合。dp[l][r]的计算方法是枚举最后一个被计算的位置i,设n1=dp[l][i],
           n2=dp[i+1][r],t1=t[l][i],t2=t[i+1][r]。那么对于加号,对于每个i要加上n1*t2+n2*t1,对于右边不同
           的组合,左边的数每次都要被加一次,同理左边不同的组合,右边的数每次也要被加一次。因此n1被加了t2次,
           n2被加了t1次。减法和加法一样。乘法是直接n1*n2。这还没完,注意就算是左边的顺序和右边的顺序的确定,
           假设左边有f1个符号,右边有f2个符号,也有C[f1+f2][f1]种排法,相当于在f1+f2个位置中选f1个,剩下的给f2,
           f1和f2中排列的相对顺序不改变,所以还要乘上C[f1+f2][f1]。同理对于每个i,t[l][r]要加上t1*t2*C[f1+f2][f1]。
*/
#include <string.h>
#include <algorithm>
#include <iostream>
#include <stdio.h>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
int n;
LL a[105],dp[105][105],num[105][105],c[105][105];
char s[105];

char getC()
{
    c[0][0]=1;
    for(int i=1;i<=100;i++)
    {
        c[i][0]=c[i][i]=1;
        for(int j=1;j<i;j++)
        {
            c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
        }
    }
}
int main()
{
    getC();
    while(~scanf("%d",&n))
    {
        for(int i=1; i<=n; i++)
            scanf("%I64d",&a[i]);
        scanf("%s",s+1);
        memset(num,0,sizeof(num));
        memset(dp,0,sizeof(dp));
        for(int i=1; i<=n; i++)
        {
            num[i][i]=1;
            dp[i][i]=a[i];
        }
        for(int i=n-1; i>=1; i--)
        {
            for(int j=i+1; j<=n; j++)
            {
                LL cnt=0;
                for(int k=i; k<j; k++)
                {
                    if(s[k]=='*')
                    {
                        cnt=(dp[i][k]*dp[k+1][j])%mod;
                    }
                    else if(s[k]=='-')
                    {
                        cnt=((dp[i][k]*num[k+1][j])%mod-(dp[k+1][j]*num[i][k])%mod)%mod;
                    }
                    else
                    {
                        cnt=((dp[i][k]*num[k+1][j])%mod+(dp[k+1][j]*num[i][k])%mod)%mod;
                    }
                    dp[i][j]=(dp[i][j]+c[j-i-1][k-i]*cnt%mod)%mod;
                    num[i][j]=(num[i][j]+num[i][k]*num[k+1][j]%mod*c[j-i-1][k-i]%mod)%mod;
                }
                //printf("%d %d:%I64d\n",i,j,dp[i][j]);
            }
        }
        printf("%I64d\n",(dp[1][n]+mod)%mod);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-29 22:29:42

hdu 5396 区间dp+组合的相关文章

HDU 5396 区间DP 数学 Expression

题意:有n个数字,n-1个运算符,每个运算符的顺序可以任意,因此一共有 (n - 1)! 种运算顺序,得到 (n - 1)! 个运算结果,然后求这些运算结果之和 MOD 1e9+7. 分析: 类比最优矩阵链乘,枚举区间[l, r]中最后一个运算符的位置k. 如果运算符为乘法的话,那么根据乘法分配率这个乘法会分配进去. 这个区间中一共有r - l个运算符,其中最后一个运算符已经定了是第k个,左区间[l, k]有k - l个运算符,右区间[k + 1, r]有 r - k - 1 个运算符. 而且左

hdu 5396 区间DP

Expression Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 482    Accepted Submission(s): 284 Problem Description Teacher Mai has n numbers a1,a2,?,anand n?1 operators("+", "-" o

HDU 5396 Expression(DP+组合数)(详解)

题目大意: 给你一个n然后是n个数. 然后是n-1个操作符,操作符是插入在两个数字之间的. 由于你不同的运算顺序,会产生不同的结果. 比如: 1 + 1 * 2 有两种  (1+1)*2   或者  1+(1*2) 1 *  2 * 3  也是两种即使结果是一样的  (1*2)*3  或者 1*(2*3) 问这所有不同的组合加起来的和对 1e9+7取余是多少. 这个其实就是区间DP了 dp[i][j] 代表的是区间  i 到 j 的和 枚举dp[i][j] 之间所有的子区间 假如是乘法: t =

HDU 5115 区间DP

有n只狼,每只狼有两种属性,一种攻击力一种附加值,每杀一只狼 受到的伤害值为这只狼的攻击值与它旁边的两只狼的附加值的和,求把所有狼都杀光受到的最小的伤害值. 注意:如果杀死中间的狼,两边的狼会紧凑过来,也就是说中间不存在空位 很明显的区间DP dp[i][k]=Min(dp[i][k],dp[i][l-1]+dp[l+1][k]+a[l]+b[i-1]+b[k+1]); // i位置起始到k位置,最后杀死k位置的狼 #include "stdio.h" #include "s

hdu 4283 区间dp

You Are the One Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3878    Accepted Submission(s): 1793 Problem Description The TV shows such as You Are the One has been very popular. In order to m

2016 ACM/ICPC Asia Regional Shenyang Online 1009/HDU 5900 区间dp

QSC and Master Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 859    Accepted Submission(s): 325 Problem Description Every school has some legends, Northeastern University is the same. Enter

HDU 5273 区间DP

输入一组数,m次询问 问每一个询问区间的逆序数有多少 区间DP简单题 #include "stdio.h" #include "string.h" int dp[1010][1010],a[1010]; int main() { int n,m,i,j,k; while (scanf("%d%d",&n,&m)!=EOF) { for (i=1;i<=n;i++) scanf("%d",&a[i]

hdu 4293 区间DP

1 /* 2 题目大意:n个人分成若干组,每个人都描叙他们组前面有多少人后面有多少人, 3 求说真话的人最多有多少个. 4 解题思路:把同一组的人数统计起来他们组前面有x人后面有y人, 5 num[x+1][n-y]表示区间[x+1,n-y]的权值,num[x+1][n-y]<=n-x-y 6 那么就是求不重合,[1,n]区间的最大值 7 */ 8 #include <iostream> 9 #include <cstdio> 10 #include <cstring&

hdu 4745 区间dp

题意:求一个环的最长回文序列,是序列不是串 链接:点我 起点是可以任意的, 所以只要求出每个区间的最长回文序列之后取max(dp[1][i]+dp[i+1][n]),即可得最终答案 本来是想扩展两倍的,但是后来的最大不太好想 将 环倍增成链,求出窗口为n的最长子序列,但这不是最终的解,你可以试看看Sample 2,是只能得出4,因为它在选中的回文外面还可以选中一个当做起点来跳,所以外面得判断找出来的回文外面是否还有可以当起点的石头,即可以找窗口为(n- 1)的长度+1.所以解即找 窗口为n的长度