题目大意:
给你一个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 = dp[i][k] * dp[k+1][j];
这个其实可以直接算出来的:
假设我们dp[i][k] 里面所有的值是 (x1+x2+x3...xn) == dp[i][k]
假设我们dp[k+1][j] 里面所有的值是 (y1+y2+y3...yn) == dp[k+1][j]
dp[i][k] * dp[k+1][j] == (x1+x2+...xn) * (y1+y2+y3...yn) == x1*y1+x1y*y2......xn*yn 其实和所有不同结果相乘出来是一样的
 
假如是加法或者减法:
我们表示阶乘 i为A[i].
t = dp[i][k]*A[j-k-1] + dp[k+1][j]*A[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] + t*C[j-i-1][k-i]
这个其实就是从总的运算符(j-i-1)(减去了第k个的运算符)个中选取(k-i)个进行运算。
因为我们选取数达到 k-i的时候,另外我们还需要保持左右两边运算的相对顺序。
就比如说:左边有a 个运算符, 右边有b个运算符。
我们从 a+b个位置中选取 a位置个放a个的运算符。其余的只能放另一边的的运算符了。因为我们左右两边的相对顺序是不变的。
 
 
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define INF 0x3fffffff
#define maxn 110 typedef long long LL;
const LL MOD = 1e9+; LL A[maxn], C[maxn][maxn];
char op[maxn];
LL dp[maxn][maxn]; int main()
{
int n;
A[] = ;
for(int i=; i<=; i++)
A[i] = (A[i-] * i)%MOD;
C[][] = ;
for(int i=; i<=; i++)
{
C[i][] = ;
for(int j=; j<=i; j++)
C[i][j] = (C[i-][j-] + C[i-][j])%MOD;
} while(scanf("%d", &n) != EOF)
{
memset(dp, , sizeof(dp));
for(int i=; i<=n; i++)
scanf("%I64d", &dp[i][i]);
scanf("%s", op+); for(int L=; L <= n; L++)
{
for(int i=; i+L- <= n; i++)
{
int j = i + L - ;
dp[i][j] = ;
for(int k=i; k<j; k++)
{
LL t;
if(op[k] == '*')
t = (dp[i][k] * dp[k+][j])%MOD;
if(op[k] == '+')
t = (dp[i][k]*A[j-k-] + dp[k+][j]*A[k-i])%MOD;
if(op[k] == '-')
t = (dp[i][k]*A[j-k-] - dp[k+][j]*A[k-i])%MOD; dp[i][j] = (dp[i][j] + t * C[j-i-][k-i])%MOD;
}
}
} printf("%I64d\n", (dp[][n]+MOD)%MOD );
}
return ;
}

HDU 5396 Expression(DP+组合数)(详解)的更多相关文章

  1. HDU 1693 插头dp入门详解

    放题目链接   https://vjudge.net/problem/22021/origin 给出一个n*m的01矩阵,1可走0不可通过,要求走过的路可以形成一个环且可以有多个环出现,问有多少不同的 ...

  2. 状压DP入门详解+题目推荐

    在动态规划的题型中,一般叫什么DP就是怎么DP,状压DP也不例外 所谓状态压缩,一般是通过用01串表示状态,充分利用二进制数的特性,简化计算难度.举个例子,在棋盘上摆放棋子的题目中,我们可以用1表示当 ...

  3. hdu 5396 Expression(区间dp)

    Problem Description Teacher Mai has n numbers a1,a2,⋯,anand n−1 operators("+", "-&quo ...

  4. HDU 5396 区间DP 数学 Expression

    题意:有n个数字,n-1个运算符,每个运算符的顺序可以任意,因此一共有 (n - 1)! 种运算顺序,得到 (n - 1)! 个运算结果,然后求这些运算结果之和 MOD 1e9+7. 分析: 类比最优 ...

  5. 2015 Multi-University Training Contest 9 hdu 5396 Expression

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

  6. 【动态规划】树形DP完全详解!

    蒟蒻大佬时隔三个月更新了!!拍手拍手 而且是更新了几篇关于DP的文章(RioTian狂喜) 现在赶紧学习和复习一下树形DP.... 树形DP基础:Here,CF上部分树形DP练习题:Here \[QA ...

  7. poj1417 true liars(并查集 + DP)详解

    这个题做了两天了.首先用并查集分类是明白的, 不过判断是否情况唯一刚开始用的是搜索.总是超时. 后来看别人的结题报告, 才恍然大悟判断唯一得用DP. 题目大意: 一共有p1+p2个人,分成两组,一组p ...

  8. Rikka with Subset HDU - 6092 (DP+组合数)

    As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some mat ...

  9. 数位DP模板详解

    // pos = 当前处理的位置(一般从高位到低位) // pre = 上一个位的数字(更高的那一位) // status = 要达到的状态,如果为1则可以认为找到了答案,到时候用来返回, // 给计 ...

随机推荐

  1. AndroidManifest.xml中的application中的name属性 分类: android 学习笔记 2015-07-17 16:51 116人阅读 评论(0) 收藏

    被这个不起眼的属性折磨了一天,终于解决了. 由于项目需要,要合并两个android应用,于是拷代码,拷布局文件,拷values,所有的都搞定之后程序还是频频崩溃,一直没有找到原因,学android时间 ...

  2. Configuring Robolectric

    There are numerous ways to customize how Robolectric behaves at runtime. Config Annotation The prima ...

  3. Bginfo软件在域的部署和应用

    在企业的IT管理中,很多用户都不知道怎么去查看自己计算机的IP地址.登陆帐户.而对于网络管理人员来说,他们可能需要知道用户在域中登录的一些信息,如那些用户登录过,在什么时间登录,IP和MAC地址是多少 ...

  4. Android 5.0以上手机出现找不到so文件

    问题描述 最近做项目出了一个bug项目中用到so文件,在5.0以上的手机上会报一个初始化异常错误,并提示找不到so文件.lib里目录结构类似如下  在Android5以下都没有问题,在5.0以上会报错 ...

  5. listActivity和ExpandableListActivity的简单用法

    http://www.cnblogs.com/limingblogs/archive/2011/10/09/2204866.html 今天自己简单的总结了listActivity和Expandable ...

  6. mksquash_lzma-3.2 编译调试记录

    今天在编译mksquash_lzma-3.2的时候出现了如下问题: /home/test/RT288x_SDK/toolchain/mksquash_lzma-3.2/lzma443/C/7zip/C ...

  7. NRPE: Unable to read output 问题处理总结

    自定义nagios监控命令check_disk_data,首先在nagios服务端command.cfg定义了#'check_disk_data' command definitiondefine c ...

  8. Java环境的安装与配置

    Java环境的安装与配置 环境:Java8,win10 推荐oracle官网oracle官网https://www.oracle.com/index.html下载JDK进行安装 选择自己需要的版本下载 ...

  9. 更新xcode后插件失效问题——不针对特定版本的通用解决方法

    一.Xcode更新后插件失效的原理 1.每次更新Xcode后插件都会失效,其实插件都还在这个目录好好的躺着呢: ~/Library/Application Support/Developer/Shar ...

  10. 绘图quartz之渐变

    实现线性渐变   径向渐变   自己新建的view中有一个drawRect:(cgrect)rect方法 在这个方法里 可以通过画图 将内容显示在画板上(即最下边的view)   渐变的方式分两种   ...