复制代码
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//n(n<=200)个数字,n-1个运算符,运算符分别是"+,-,*" //可以改变运算符大的运算顺序,那么有(n-1)!中运算结果 //问所有这些结果的和 //区间dp应该很好想到 //dp[i][j] 表示从i开始的j个数的(j-1)!中运算结果之和 //枚举最一个运算的运算符的位置 //那么对于'*'操作由于其分配率可以直接左右区间相乘就行 //对于'+'和'-'操作需要乘上另一个区间的情况的个数 //还有就是这些区间操作的顺序 //由于枚举了最后一个操作,左边区间和右边区间各自的顺序也确定 //但是左边和右边一起的顺序没有确定,这种情况的个数 //设左边区间x个操作符,右边y个 //那么情况个数就为c[x+y][x]个 #include<cstdio> #include<cstring> #include<iostream> using namespace std ; const int maxn = 110 ; typedef long long ll ; const ll mod = 1e9+7 ; ll dp[maxn][maxn] ; ll c[maxn][maxn] ; ll A[maxn] ; char str[maxn] ; void init() { A[0] = 1 ; for(int i = 1;i < maxn;i++) A[i] = (A[i-1]*i)%mod ; for(int i = 0;i < maxn;i++) c[i][0] = c[i][i] = 1 ; for(int i = 1;i < maxn;i++) for(int j = 1;j < maxn;j++) c[i][j] = (c[i-1][j-1]+c[i-1][j])%mod ; } int main() { int n ; init() ; while(~scanf("%d" , &n)) { for(int i = 1;i <= n;i++) scanf("%lld" , &dp[i][1]) ; scanf("%s" , &str[1]) ; for(int j = 2;j <= n;j++) for(int i = 1;i <= n-j+1;i++) { dp[i][j] = 0 ; for(int k = 1;k < j;k++) { ll tmp ; if(str[i+k-1] == '+') tmp = (dp[i][k]*A[j-k-1]+dp[i+k][j-k]*A[k-1])%mod ; else if(str[i+k-1] == '-') tmp = (dp[i][k]*A[j-k-1]-dp[i+k][j-k]*A[k-1])%mod ; else if(str[i+k-1] == '*') tmp = (dp[i][k]*dp[i+k][j-k])%mod ; tmp = tmp*c[j-2][k-1]%mod ; dp[i][j] =(dp[i][j] + tmp)%mod ; } } printf("%lldn" , (dp[1][n]+mod)%mod) ; } return 0 ; }
最后
以上就是仁爱橘子最近收集整理的关于hdu5396Expression 区间dp的全部内容,更多相关hdu5396Expression内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复