【区间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 & ...
随机推荐
- Base64编码与解码 分类: 中文信息处理 2014-11-03 21:58 505人阅读 评论(0) 收藏
Base64是一种将二进制转为可打印字符的编码方法,主要用于邮件传输.Base64将64个字符(A-Z,a-z,0-9,+,/)作为基本字符集,把所有符号转换为这个字符集中的字符. 编码: 编码每次将 ...
- Spring MVC 结合Velocity视图出现中文乱码的解决方案
编码问题一直是个很令人头疼的事,这几天搭了一个Spring MVC+VTL的web框架,发现中文乱码了,这里记录一种解决乱码的方案. 开发环境为eclipse,首先,检查Window->pref ...
- windows8.1专业版 关闭ie11总是已停止工作
该问题通常原因: 1 系统重病毒: 2 系统和安装的软件不兼容导致. 解决方案: 1 杀毒更新至最新进行杀毒,仍未解决,重新安装系统: 2 目前身边人员多数属于该情况: 1 如安装了输入法.迅雷或其它 ...
- hihocoder 分隔相同字符
思路: 枚举,贪心. 在“合法”的前提下放置越排在前边的字母越好. “合法”:'a' - 'z'中没有一个字母的个数超过当前串剩余长度的一半(偶数情况下)或长度的一半加1(奇数情况下). 实现: #i ...
- 学习笔记 第十二章 CSS3+HTML5网页排版
第12章 CSS3+HTML5网页排版 [学习重点] 正确使用HTML5结构标签 正确使用HTML5语义元素 能够设计符合标准的网页结构 12.1 使用结构标签 在制作网页时,不仅需要使用< ...
- mysql 修改 root 密码
5.76中加了一些passwd的策略 MySQL's validate_password plugin is installed by default. This will require that ...
- 在windows下用python调用darknet的yolo接口
0,目标 本人计算机环境:windows7 64位,安装了vs2015专业版,python3.5.2,cygwin,opencv3.3,无gpu 希望实现用python调用yolo函数,实现物体检测. ...
- 关于 Oracle 11g r2 Enterprise Manager (EM) 在windows环境无法启动的解决办法
正确的解决办法是在安装的时候使用emca正确安装 如果已经安装过Enterprise Manager: 请用是如下命令卸载后重装 emca -deconfig dbcontrol db emca -r ...
- SQL SERVER的数据类型
1.SQL SERVER的数据类型 数据类弄是数据的一种属性,表示数据所表示信息的类型.任何一种计算机语言都定义了自己的数据类型.当然,不同的程序语言都具有不同的特点,所定义的数据类型的各类和名称都或 ...
- Javascript IE 内存释放
一个内存释放的实例 <SCRIPT LANGUAGE="JavaScript"><!--strTest = "1";for ( var i = ...