题意:有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 个运算符。

而且左、右区间运算符的先后顺序确定以后,两个区间之间的顺序是互不影响的,因此这样相同的结果一共有C(r - l - 1, k - l)

因此答案还要乘上这个数,d(i, j) += d(i, k) * d(k + 1, r) * C(r - l - 1, k - l) | op[k] = *

但如果是加减法的话就不能直接按照运算符进行区间合并了。

对于左区间的确定的一个运算顺序,右区间一共有 (r - k - 1)! 个运算结果,所以答案累加一个 d(l, k) * (r - k - 1)!

同样地,对于右区间一个确定的操作顺序,左区间对应有 (k - l)! 个运算结果,答案累加一个 d(k + 1, r) * (k - l)!

最后确定两个区间 r - l - 1 个运算符的顺序,最终答案乘上 C(r - l - 1, k - l)

最后总结一下答案就是:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. using namespace std;
  6.  
  7. typedef long long LL;
  8.  
  9. const int maxn = + ;
  10. const LL MOD = ;
  11.  
  12. int n;
  13. LL a[maxn];
  14. LL fac[maxn], C[maxn][maxn];
  15. char op[maxn];
  16.  
  17. int vis[maxn][maxn];
  18. LL d[maxn][maxn];
  19.  
  20. LL dp(int l, int r)
  21. {
  22. if(vis[l][r]) return d[l][r];
  23. LL& ans = d[l][r];
  24. ans = ;
  25. vis[l][r] = true;
  26. if(l == r) return ans = a[l];
  27. if(l + == r)
  28. {
  29. if(op[l] == '*') return ans = a[l] * a[r] % MOD;
  30. if(op[l] == '+') return ans = (a[l] + a[r]) % MOD;
  31. if(op[l] == '-') return ans = (((a[l] - a[r]) % MOD) + MOD) % MOD;
  32. }
  33. for(int k = l; k < r; k++)
  34. {
  35. LL t1 = dp(l, k), t2 = dp(k + , r);
  36. LL t;
  37. if(op[k] == '*')
  38. {
  39. t = t1 * t2 % MOD;
  40. t = t * C[r - l - ][k - l];
  41. ans = (ans + t) % MOD;
  42. continue;
  43. }
  44.  
  45. t1 = t1 * fac[r - k - ] % MOD;
  46. t2 = t2 * fac[k - l] % MOD;
  47. if(op[k] == '+') t = (t1 + t2) % MOD;
  48. else t = (((t1 - t2) % MOD) + MOD) % MOD;
  49. t = t * C[r - l - ][k - l];
  50. ans = (ans + t) % MOD;
  51. }
  52.  
  53. return ans;
  54. }
  55.  
  56. int main()
  57. {
  58. fac[] = ;
  59. for(int i = ; i < maxn; i++) fac[i] = fac[i - ] * i % MOD;
  60. for(int i = ; i < maxn; i++) C[i][] = C[i][i] = 1LL;
  61. for(int i = ; i < maxn; i++)
  62. for(int j = ; j < i; j++) C[i][j] = (C[i-][j] + C[i-][j-]) % MOD;
  63.  
  64. while(scanf("%d", &n) == && n)
  65. {
  66. for(int i = ; i <= n; i++) scanf("%I64d", a + i);
  67. scanf("%s", op + );
  68. memset(vis, false, sizeof(vis));
  69. memset(vis, , sizeof(vis));
  70. printf("%I64d\n", dp(, n));
  71. }
  72.  
  73. return ;
  74. }

代码君

HDU 5396 区间DP 数学 Expression的更多相关文章

  1. hdu 4283 区间dp

    You Are the One Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  2. HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化

    HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化 n个节点n-1条线性边,炸掉M条边也就是分为m+1个区间 问你各个区间的总策略值最少的炸法 就题目本身而言,中规中矩的 ...

  3. HDU 4293---Groups(区间DP)

    题目链接 http://acm.split.hdu.edu.cn/showproblem.php?pid=4293 Problem Description After the regional con ...

  4. String painter HDU - 2476 -区间DP

    HDU - 2476 思路:分解问题,先考虑从一个空串染色成 B串的最小花费 ,区间DP可以解决这个问题 具体的就是,当 str [ l ] = = str [ r ]时 dp [ L ] [ R ] ...

  5. HDU 4632 区间DP 取模

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4632 注意到任意一个回文子序列收尾两个字符一定是相同的,于是可以区间dp,用dp[i][j]表示原字 ...

  6. 2016 ACM/ICPC Asia Regional Shenyang Online 1009/HDU 5900 区间dp

    QSC and Master Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) ...

  7. HDU 4570(区间dp)

    E - Multi-bit Trie Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u ...

  8. hdu 2476 区间dp

    题意: 给出两个串s1和s2,一次只能将一个区间刷一次,问最少几次能让s1=s2 例如zzzzzfzzzzz,长度为11,我们就将下标看做0~10 先将0~10刷一次,变成aaaaaaaaaaa 1~ ...

  9. hdu 4632(区间dp)

    Palindrome subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65535 K (Java/ ...

随机推荐

  1. 2.语言概述-JavaScript权威指南笔记

    上周三的时候交给老板目前的项目第一个迭代回顾会的总结.原本是以综述性的表述方式写的,交给他之后表示程序员不要长篇大论.总结要分为优点缺点期望等等块,每块列出条目,简明扼要的表达出来.这里也用这种风格. ...

  2. 如何构建多模块的SpringBoot项目

    通过阅读本文你将了解到:如何将已有SpringBoot项目改成多模块 & 如何新构建多模块SpringBoot项目 以下示例基于我正在使用的order(订单服务)进行演示,无论你用的是什么项目 ...

  3. 使用Robot类模拟鼠标、键盘事件

    Robot类用于模拟鼠标.键盘事件,生成本机系统输入事件.Robot 的主要用于自动化.自运行的程序和其他需要自动控制鼠标和键盘的程序 相当于实际操作的效果,不仅仅只是生成对应的鼠标.键盘事件.比如R ...

  4. 使用Calendar来获取当前日期和时间

    1 package com.java.test; 2 3 import java.text.SimpleDateFormat; 4 import java.util.Calendar; 5 6 pub ...

  5. specrate 与specspeed 的区别

    What is the difference between a "rate" and a "speed" metric?There are several d ...

  6. MFC制作简单通讯录程序

    学习c++和MFC一段时间了,苦于没有项目实战,所以自己写了一个简单的简单通讯录程序,以前用c#写简单很多,例程是这本书上的实例,我的第一个winform程序也是从这本书上学的,总结c#写的话更简单, ...

  7. cmd下查询端口占用以及根据进程id名称结束进程

    cmd窗口中: C:\Users\insentek>netstat -aon|findstr "1099" TCP 0.0.0.0:1099 0.0.0.0:0 LISTEN ...

  8. 【转】iOS学习笔记(十七)——文件操作(NSFileManager)

    iOS的沙盒机制,应用只能访问自己应用目录下的文件.iOS不像android,没有SD卡概念,不能直接访问图像.视频等内容.iOS应用产生的内容,如图像.文件.缓存内容等都必须存储在自己的沙盒内.默认 ...

  9. 【vue iview】项目 win10 放在C盘 经常npm install不成功,就是因为 权限问题,把代码目录放到D盘就没事了。

    [vue iview]项目 win10 放在C盘 经常npm install不成功,就是因为 权限问题,把代码目录放到D盘就没事了.

  10. 禁止DataGridView控件中添加和删除行

    实现效果: 知识运用: DataGridView控件的AllowUserToAddRows AllowUserDeleteRows和ReadOnly属性 实现代码: private void btn_ ...