【区间dp+组合数+数学期望】Expression
https://www.bnuoj.com/v3/contest_show.php?cid=9148#problem/I
【题意】
给定n个操作数和n-1个操作符,组成一个数学式子。每次可以选择两个相邻操作数及中间的操作符进行运算,如a-b变成一个数(a-b),直到这个式子变成一个数。同一个初始式子可以进行不同的操作,最后的结果也可能不同。最后求不同操作得到结果的和(mod 1000 000 007)
对于两个操作,只要存在一步是不同的,这两个操作就被认为是不同的。
【思路】
总体思路是区间dp,对于dp[i][j],枚举k(i<=k<j),考察dp[i][k]和dp[k+1][j]
具体做的时候可以分别考虑*,+,-三种运算,用组合数学;
还有一种非常非常巧妙的办法:数学期望!
组合数学:
比较明显的区间dp,令dp[l][r]为闭区间[l,r]的所有可能的结果和,考虑最后一个符号的位置k,k必须在l,r之间,则l≤k<r,dp[l][r]=Σ{dp[l][k]?dp[k+1][r]}*(r-l-1)!/[(k-l)!(r-k-1)!],其中(r-l-1)!/[(k-l)!(r-k-1)!]表示从左区间和右区间选择符号的不同方法总数(把左右区间看成整体,那么符号的选择在整体间也有顺序,内部的顺序不用管,那是子问题需要考虑的),相当于(k-l)个0和(r-k-1)个1放一起的不同排列方法总数。
对花括号里面的‘?‘分为三种情况:
(1)‘+‘ 假设左区间有x种可能的方法,右区间有y种可能的方法,由于分配律的存在,左边的所有结果和会重复计算y次,右边的所有结果和会重复计算x次,而左边共(k-l)个符号,右边共(r-k-1)个符号,所以合并后的答案dp[l][r]=dp[l][k]*(r-k-1)!+dp[k+1][r]*(k-l)!
(2)‘-‘ 与‘+‘类似
(3)‘*‘ 由分配律,合并后的答案dp[l][r]=dp[l][k]*dp[k+1][r]
数学期望:
如果将这个过程随机化,即每次等概率地选取相邻两项合并,
记dp[i][j]为随机合并第i个到第j个数字这一段的表达式之后结果的期望,
根据期望的线性可加性,状态转移方程为
dp[i][j]=(sigma_(k=i~j-1)(dp[i][k]?dp[k+1][j]))/(j-i),
其中"?"表示第k个数与第k+1个数之间的运算符,
那么dp[1][n]即为随机合并整个表达式之后结果的期望,
乘上方案数(n-1)!即为所求的总和,
由于是取模意义下的运算,转移方程中的除法要用逆元代替,
复杂度O(n^3)。
【Accepted】
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath> using namespace std;
typedef long long ll;
const int maxn=1e2+;
const ll mod=1e9+;
ll a[maxn];
char op[maxn];
ll dp[maxn][maxn];
ll fpow(ll x,ll n)
{
ll res=1LL;
while(n)
{
if(n&)
{
res=(res*x)%mod;
}
x=(x*x)%mod;
n>>=;
}
return res;
}
ll fact[maxn];
ll nfact[maxn];
int n;
void init()
{
fact[]=1LL;
for(int i=;i<maxn;i++)
{
fact[i]=(fact[i-]*(ll)i)%mod;
}
nfact[]=1LL;
for(int i=;i<maxn;i++)
{
nfact[i]=fpow(fact[i],mod-);
}
}
int main()
{
init();
while(~scanf("%d",&n))
{
memset(dp,,sizeof(dp));
for(int i=;i<n;i++)
{
cin>>a[i];
}
scanf("%s",op);
for(int i=;i<n;i++)
{
dp[i][i]=a[i];
}
for(int l=;l<n;l++)
for(int i=;i+l<n;i++)
{
int j=i+l;
for(int k=i;k<j;k++)
{
ll add;
if(op[k]=='+')
{
add=(dp[i][k]*fact[j--k]%mod+dp[k+][j]*fact[k-i]%mod)%mod;
}
else if(op[k]=='-')
{
add=(dp[i][k]*fact[j--k]%mod-dp[k+][j]*fact[k-i]%mod+mod)%mod;
}
else
{
add=(dp[i][k]*dp[k+][j]%mod)%mod;
}
add=(add*fact[l-]%mod*nfact[j--k]%mod*nfact[k-i]%mod)%mod;
dp[i][j]=(dp[i][j]+add)%mod;
}
}
cout<<dp[][n-]<<endl; }
return ;
}
区间dp+组合数
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath> using namespace std;
typedef long long ll;
const ll md=1e9+;
ll fpow(ll x,ll n)
{
ll res=1LL;
while(n)
{
if(n&)
{
res=(res*x)%md;
}
x=(x*x)%md;
n>>=;
}
return res;
}
const int maxn=1e2+;
ll a[maxn];
char op[maxn];
ll dp[maxn][maxn];
ll fact[maxn];
void init()
{
fact[]=1LL;
for(int i=;i<maxn;i++)
{
fact[i]=(fact[i-]*(ll)i)%md;
}
}
int n;
int main()
{
init();
while(~scanf("%d",&n))
{
memset(dp,,sizeof(dp));
for(int i=;i<n;i++)
{
cin>>a[i];
}
scanf("%s",op);
for(int i=;i<n;i++)
{
dp[i][i]=a[i];
}
for(int l=;l<n;l++)
{
for(int i=;i+l<n;i++)
{
int j=i+l;
for(int k=i;k<j;k++)
{
ll add;
if(op[k]=='+')
{
add=(dp[i][k]+dp[k+][j])%md;
}
else if(op[k]=='-')
{
add=(dp[i][k]-dp[k+][j]+md)%md;
}
else
{
add=(dp[i][k]*dp[k+][j])%md;
}
dp[i][j]=(dp[i][j]+add)%md;
}
dp[i][j]=(dp[i][j]*fpow(l,md-))%md;
}
}
ll ans=(dp[][n-]*fact[n-])%md;
cout<<ans<<endl;
}
return ;
}
区间dp+数学期望(随机化过程,期望的线性可加性)
【知识点】
1. 取模意义下的除法不能直接除,要用逆元代替。根据费马小定理,a^(p-1)=1(mod p),所以a^(p-2)=(1/a)(mod p),所以a的逆元就是a^p-2。通常p是一个很大的素数,如经常见到的1e9+7,所以要用快速幂。
快速幂模板
ll fpow(ll x,ll n)
{
ll res=1LL;
while(n)
{
if(n&)
{
res=(res*x)%mod;
}
x=(x*x)%mod;
n>>=;
}
return res;
}
2. 组合数C(i,j)有两种算法:
第一种:
fac(i+j)*nfac(i)*nfac(j)
//其中nfac(i)=fastpow(fac(i),mod-2)
第二种:
C[][]=;
for (int i=;i<;i++)
{
C[i][]=;
for (int j=;j<=i;j++)
{
C[i][j]=(C[i-][j-]+C[i-][j])%md;
}
}
3. 在取模运算下,要注意减法,a-b通常要写成(a-b+md)%md
总之注意不要算出负数
【区间dp+组合数+数学期望】Expression的更多相关文章
- [2013山东ACM]省赛 The number of steps (可能DP,数学期望)
The number of steps nid=24#time" style="padding-bottom:0px; margin:0px; padding-left:0px; ...
- CSU 1290 DP解决数学期望问题
题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1290 题目大意: 给定k个数,每次可以生成0-N-1中的任何一个数,k个数中出现不同的整 ...
- bzoj-3450 Easy概率DP 【数学期望】
Description 某一天WJMZBMR在打osu~~~但是他太弱逼了,有些地方完全靠运气:(我们来简化一下这个游戏的规则有n次点击要做,成功了就是o,失败了就是x,分数是按comb计算的,连续a ...
- poj 2057 树形DP,数学期望
题目链接:http://poj.org/problem?id=2057 题意:有一只蜗牛爬上树睡着之后从树上掉下来,发现后面的"房子"却丢在了树上面, 现在这只蜗牛要求寻找它的房子 ...
- HDU 4405 Aeroplane chess(概率dp,数学期望)
题目 http://kicd.blog.163.com/blog/static/126961911200910168335852/ 根据里面的例子,就可以很简单的写出来了,虽然我现在还是不是很理解为什 ...
- 【整理】简单的数学期望和概率DP
数学期望 P=Σ每一种状态*对应的概率. 因为不可能枚举完所有的状态,有时也不可能枚举完,比如抛硬币,有可能一直是正面,etc.在没有接触数学期望时看到数学期望的题可能会觉得很阔怕(因为我高中就是这么 ...
- 2015暑假多校联合---Expression(区间DP)
题目链接 http://acm.split.hdu.edu.cn/showproblem.php?pid=5396 Problem Description Teacher Mai has n numb ...
- HDU 5396 Expression(DP+组合数)(详解)
题目大意: 给你一个n然后是n个数. 然后是n-1个操作符,操作符是插入在两个数字之间的. 由于你不同的运算顺序,会产生不同的结果. 比如: 1 + 1 * 2 有两种 (1+1)*2 或者 ...
- 数学期望和概率DP题目泛做(为了对应AD的课件)
题1: Uva 1636 Headshot 题目大意: 给出一个000111序列,注意实际上是环状的.问是0出现的概率大,还是当前是0,下一个还是0的概率大. 问题比较简单,注意比较大小: A/C & ...
随机推荐
- Retinex系列之McCann99 Retinex 分类: 图像处理 Matlab 2014-12-03 11:27 585人阅读 评论(0) 收藏
一.McCann99 Retinex McCann99利用金字塔模型建立对图像的多分辨率描述,自顶向下逐层迭代,提高增强效率.对输入图像的长宽有 严格的限制,要求可表示成 ,且 ,. 上述限制来源于金 ...
- HTML/XML转义字符对照表
HTML/XML转义字符对照表 HTML/XML转义字符对照表包含符号.数学符号.希腊字母 .重要的国际标志.ISO 8859-1 (Latin-1)字符集.特殊符号等. 1.特殊字符转义表 字符 十 ...
- Android开发学习——android与服务器端数据交互
1.首先搭建服务器端. 使用MyEclipse开发工具 public class MyServlet extends HttpServlet { @Override protected void do ...
- mybatis的mapper.xml文件细节
- Android学习笔记(十五) Http
1.Http协议概要 应用程序和服务间的请求/响应是无状态的,即响应完即断开连接. HttpClient库是Android自带的,故无需引入该库 2.Http请求和获取数据 生成代表客户端的HttpC ...
- spring-mvc hello world (1)
我学习一个程序,都是从DEMO开始的. 先不了解SPRING-MVC的原理,但一些小的概念还是需要了解的.由于之前有过SSH的工程经验,故基本的东东,不在叙述. 1.准备环境 JAR包:
- 忘记dba用户密码,利用SQLPlus重置dba密码
打开SQL Plus 输入用户名: sys as sysdba 输入口令:可直接回车 连接到: Oracle Database 11g Enterprise Edition Release 11.2. ...
- CentOS安装使用vnc进行远程桌面登录
以下介绍在CentOS 7下安装vncserver并使用vnc-viewer进行登录(使用root权限): 1.运行命令yum install tigervnc-server安装vncserver: ...
- cp - 复制文件和目录
总览 cp [选项] 文件路径 cp [选项] 文件...目录 POSIX 选项: [-fipRr] GNU 参数(最短形式): [-abdfilprsuvxPR] [-S SUFFIX] [-V { ...
- OpenCV2:应用篇 QT+OpenCV实现图片编辑器
一.简介 做完会放在Github上