MYF

HDU 5396 Expression

题目链接

HDU 5396

组合数 + DP

题目分析

题目大意

给定n个数和n-1个符号,有这样一种操作:将相邻的两个数加括号,加n-1次括号,不同的操作有不同的运算结果,问所有结果相加对1e9+7取模,问答案是多少?

解析

挺难的一题,状态转移方程:

1
2
3
4
5
//l, r表示闭区间左右端点, pos为在在该区间中的符号位置, 遍历每一个位置
dp(l, r)+=
C(r-l-1, pos-l)*(dp(l, pos)*[(r-pos-1)!]+dp(pos+1, r)*((pos-l)!)) ,s[pos]='+'
C(r-l-1, pos-l)*(dp(l, pos)*[(r-pos-1)!]+dp(pos+1, r)*((pos-l)!)) ,s[pos]='-'
C(r-l-1, pos-l)*(dp(l, pos)*dp(pos+1, r)) ,s[pos]='*'

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <deque>
#include <algorithm>
#define Memset(a,val) memset(a,val,sizeof(a))
#define PI acos(-1)
#define rt(n) (i == n ? '\n' : ' ')
#define hi printf("Hi----------\n")
#define IN freopen("input.txt","r",stdin);
#define OUT freopen("output.txt","w",stdout);
#define debug(x) cout<<"Debug : ---"<<x<<"---"<<endl;
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long ll;
using namespace std;
const int maxn=100000+5;
const int mod=1000000007;
const int INF=0x3f3f3f3f;
const double eps=1e-8;
int n;
ll dp[105][105],C[105][105],F[105];
char s[105];
void init(){
F[0]=1;
for (int i=1; i<=100; i++)
F[i]=F[i-1]*i%mod;

C[0][0]=1;
for (int i=1; i<=100; i++) {
C[i][0]=1;
for (int j=1; j<=i; j++) {
C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
}
}
int main(){
init();
while (scanf("%d",&n)!=EOF) {

for (int i=1; i<=n; i++)
scanf("%lld",&dp[i][i]);
scanf("%s",s+1);//1~n-1

ll sum;
for (int len=2; len<=n; len++) {//区间长度
for (int l=1,r=l+len-1; r<=n; l++,r++) {//记录左右端点
dp[l][r]=0;
for (int pos=l; pos<r; pos++) {//记录符号位置
if (s[pos]=='+')
sum=(dp[l][pos]*F[r-pos-1]%mod+dp[pos+1][r]*F[pos-l]%mod)%mod;
else if (s[pos]=='-')
sum=(dp[l][pos]*F[r-pos-1]%mod-dp[pos+1][r]*F[pos-l]%mod)%mod;
else
sum=dp[l][pos]*dp[pos+1][r]%mod;

dp[l][r]=(dp[l][r]+sum*C[r-l-1][pos-l])%mod;
}
}
}

cout<<(dp[1][n]+mod)%mod<<endl;
}
}