Expression
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 380 Accepted Submission(s): 214
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 .
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.
3 3 2 1 -+ 5 1 4 6 8 3 +*-*
2 999999689HintTwo numbers are considered different when they are in different positions.
解题思路:区间DP
dp[i][j]表示区间 i 到 j 的和,枚举dp[i][j]之间所有的子区间。
如果是乘法:s = dp[i][k]*dp[k+1][j]
假设dp[i][k]的值可以表示为dp[i][k]=x1+x2+x3+……+xn
假设dp[k+1][j]的值可以表示为dp[k+1][j]=y1+y2+y3+……+ym
则dp[i][k]*dp[k+1][j]=(x1+x2+……+xn)*(y1+y2+……+ym)=x1*y1+x1*y2+……+xn*ym
其实和所有不同结果相乘出来是一样的。
如果是加法或者是减法:
以fac[i]的值表示i的阶乘,s = dp[i][k]*fac[j-k-1]+dp[k+1][j]*fac[k-i]
其实这里我们想一下。区间 dp[i][k] 需要加上多少次?我们需要加的次数就是另一半区间的所有组合数,另一半区
间有多少种组合方式我们就要加上多少个。因为他们之间可以相互组成不同的种类。同理另一半也是。
最后我们还要乘上一个组合数。
假设组合数为C[i][j].
为什么要乘组合数:
因为 假如我们k 分割了两个运算式子 【 1+(2*3) 】 + 【 1+(3*4) 】
虽然说我们左右两边的式子运算顺序已经确定了,但是我们总的运算顺序还是不确定的, 比如我们算完(2*3)直接
去算(3*4)也是不同的结果
dp[i][j] = dp[i][j] + s*C[j-i-1][k-i]
这个其实就是从总的运算符(j-i-1)(减去了第k个的运算符)个中选取(k-i)个进行运算。
因为我们选取数达到 k-i的时候,另外我们还需要保持左右两边运算的相对顺序。
就比如说:左边有a 个运算符, 右边有b个运算符。
我们从 a+b个位置中选取 a位置个放a个的运算符。其余的只能放另一边的的运算符了。因为我们左右两边的相对顺
序是不变的。
代码如下:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#include <limits.h>
#define debug "output for debug\n"
#define pi (acos(-1.0))
#define eps (1e-6)
#define inf (1<<28)
#define mod 1000000007
#define sqr(x) (x) * (x)
using namespace std;
typedef long long ll;
typedef unsigned long long ULL;
const int MAX = 105;
ll n,dp[MAX][MAX],fac[MAX],c[MAX][MAX];
char op[MAX];
void init()
{
ll i,j;
fac[0]=1;
for(i=1;i<=100;i++)
fac[i]=i*fac[i-1]%mod;
c[0][0]=1;
for(i=1;i<=100;i++)
{
c[i][0]=1;
for(j=1;j<=i;j++)
c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
}
int main()
{
ll i,j,k,l;
init();
while(~scanf("%I64d",&n))
{
memset(dp, 0, sizeof(dp));
for(i=1;i<=n;i++)
scanf("%I64d",&dp[i][i]);
scanf("%s",op+1);
for(l=2;l<=n;l++)
{
for(i=1;i+l-1<=n;i++)
{
j=i+l-1;
dp[i][j]=0;
for(k=i;k<j;k++)
{
ll s;
if(op[k]=='*')
s=(dp[i][k]*dp[k+1][j])%mod;
if(op[k]=='+')
s=(dp[i][k]*fac[j-k-1]+dp[k+1][j]*fac[k-i])%mod;
if(op[k]=='-')
s=(dp[i][k]*fac[j-k-1]-dp[k+1][j]*fac[k-i])%mod;
dp[i][j]=(dp[i][j]+s*c[j-i-1][k-i])%mod;
}
}
}
printf("%I64d\n",(dp[1][n]+mod)%mod);
}
return 0;
}