HDOJ 5396 Expression DP

记dp_{l,r}dp?l,r??表示l,rl,r这段数能形成的答案总和。

枚举最后一步操作kk,如果是乘法,答案为dp_{l,k}*dp_{k+1,r}dp?l,k???dp?k+1,r??,由于分配率这个会乘开来。如果是加法那么是dp_{l,r}*(r-k-1)!+dp_{k+1,r}*(k-l)!dp?l,r???(r?k?1)!+dp?k+1,r???(k?l)!,即要乘上右边k+1,rk+1,r这些数所有可行的方案数,减法同理。最后乘上{r-l-2
\choose k-l}(?k?l?r?l?2??),即把两边操作合起来的方案数。

答案为dp_{1,n}dp?1,n??。

Expression

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 447    Accepted Submission(s): 260

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.

Author

xudyh

Source

2015 Multi-University Training Contest 9

/* ***********************************************
Author        :CKboss
Created Time  :2015年08月19日 星期三 21时58分12秒
File Name     :HDOJ5396.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

typedef long long int LL;

const int maxn=210;
const LL mod=1e9+7LL;

int n;
LL a[maxn];
char ope[maxn],cmd[maxn];
LL dp[maxn][maxn];
LL C[maxn][maxn];
LL jc[maxn];

void init()
{
	jc[0]=1; C[0][0]=1LL;
	for(int i=1;i<maxn;i++)
	{
		C[i][i]=C[i][0]=1LL;
		jc[i]=(jc[i-1]*i)%mod;
	}
	for(int i=1;i<maxn;i++)
	{
		for(int j=1;j<i;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
	}
}

void DP()
{
	memset(dp,0,sizeof(dp));
	for(int i=1;i<=n;i++) dp[i][i]=a[i];
	for(int len=2;len<=n;len++)
	{
		for(int i=1;i+len-1<=n;i++)
		{
			int j=i+len-1;
			for(int k=i;k<j;k++)
			{
				int left=k-i;
				int right=len-2-left;
				LL t=0;
				if(ope[k]=='*')
				{
					t=(dp[i][k]*dp[k+1][j])%mod;
				}
				else if(ope[k]=='+')
				{
					t=(dp[i][k]*jc[right]%mod+dp[k+1][j]*jc[left]%mod)%mod;
				}
				else if(ope[k]=='-')
				{
					t=(dp[i][k]*jc[right]%mod-dp[k+1][j]*jc[left]%mod+mod)%mod;
				}
				dp[i][j]=(dp[i][j]+t*C[len-2][left]%mod)%mod;
			}
		}
	}
}

int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);

	init();
	while(scanf("%d",&n)!=EOF)
	{
		for(int i=1;i<=n;i++) scanf("%lld",a+i);
		scanf("%s",cmd+1);
		for(int i=1;i<n;i++) ope[i]=cmd[i];
		DP();
		printf("%lld\n",dp[1][n]%mod);
	}

    return 0;
}

版权声明:来自: 码代码的猿猿的AC之路 http://blog.csdn.net/ck_boss

时间: 2024-10-12 14:47:32

HDOJ 5396 Expression DP的相关文章

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 5396 Expression (MUT#9 区间DP)

[题意]:click here~~ [题目大意]: 给你一个一行包含n(2=<n<=100)个数字的式子,和一个字符串(2=<s<=100),字符串里包含三种运算符号:+,-,*,且s=n-1,也就是说在每两个数字之间,插入n-1个符号,位置已经在输入的时候固定了,现在你要做的就是可以自由安排符号的运算顺序,每轮选择之后,将会得到一个结果,求所有的结果的和 [思路]:区间DP: 先贴一下题解(感觉题解有个地方写错了): 设DP[l][r]:表示区间[l,r]这段里面能形成的答案的总

hdoj 1087 (DP)

代码: #include<iostream>   #include<cmath>   using namespace std;  int a[1005], dp[1005];  int main()  {      int n,sum,i,j;      while( scanf("%d",&n)&&n){             for( i=0; i<n; i++){                  scanf("%

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

HDU 5396 Expression (区间DP)

链接 : http://acm.hdu.edu.cn/showproblem.php?pid=5396 设d[i][j] 代表i~j的答案.区间DP枚举(i, j)区间的断点,如果断点处的操作符是'*',那么该区间的答案可以直接加上d[i][k] *  d[k+1][j],因为乘法分配律可以保证所有的答案都会乘起来.如果是加法,需要加的 就是 左边的答案 乘 右边操作数的阶乘 加上 右边的答案乘左边操作数的阶乘,最后要确定左边操作和右边操作的顺序 因为每个答案里是统计了该区间所有的阶乘情况,因此

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 Expression(区间dp)

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+

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,枚举最后一步操作k,对乘法,答案为 dp[i,k]?dp[k+1,r],由于分配率这个会乘开来. 如果是加法那么是dp[i][k]?(j?k?1)!+dp[k+1][j]?(k?i)!,减法同理. 最后还要乘以C(j?i?1,k?i) #include <bits/stdc++.h> using namespace std; #define prt(k) cerr<<#k" = "<<k<<endl typedef lo