【区间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 & ...
随机推荐
- 数组声明的几种方式以及length属性
声明一: int[] arr=new int[10]; for(int i=0;i<arr.length;i++){ arr[i]=i; } 声明二: int[] arr2={1,2,3}; 声 ...
- chromedriver与chrome版本对应
今天把手头有的一些关于selenium测试的资源整理了一下,分享出来. 1. 所有版本chrome下载 是不是很难找到老版本的chrome?博主收集了几个下载chrome老版本的网站,其中哪个下载的是 ...
- ambari-server启动报错500 status code received on GET method for API:/api/v1/stacks/HDP/versions/2.4/recommendations Error message : Server Error解决办法(图文详解)
问题详情 来源是,我在Ambari集群里,安装Hue. 给Ambari集群里安装可视化分析利器工具Hue步骤(图文详解 所遇到的这个问题. 然后,去ambari-server的log日志,查看,如下 ...
- AJPFX学习Java函数知识总结
函 数:为了提高代码的复用性,可以将其定义成一个单独的功能,该功能的体现就是java中的函数.函数就是体现之一. java中的函数的定义格式: 修饰符 返回值类型 函数名(参数类型 形 ...
- poj3040 Allowance
思路: 贪心. 看了题解说是 先把面值从大到小排序然后从头往尾扫,只要不超额,能取多少去多少然后如果还有剩余,就从尾往头扫,尽量取,让他恰好超额 不过并不懂证明. 实现: #include <i ...
- Elasticsearch--集群&吞吐量
目录 高查询和高吞吐量 过滤器缓存 字段数据缓存和断路器 断路器 存储模块 索引缓冲和刷新率 索引刷新率 线程池的配置 一些通用的建议来配置高索引和查询吞吐量的集群 高查询和高吞吐量 过滤器缓存 过滤 ...
- .NET 使用 Highcharts生成扇形图 柱形图
1.首先新建一个.NET网站,如图所示: 2.引用所需要的js类库,如下图 highcharts.js可以在网上搜索就可以找到下载了. 3.在Default.aspx页面引用js 4.在 body 下 ...
- 键盘工具栏的快速集成--IQKeyboardManager
转自:http://www.cnblogs.com/gaoxiaoniu/p/5333187.html 键盘工具栏的快速集成--IQKeyboardManager IQKeyboardManager, ...
- vba,excel,网址提取名字与链接url
'宏操作 Sub 复制超级链接() '这里控制读取A列的第1到10行,你根据自已的要求修改一下起始和结束行数 ).Hyperlinks.Count > ).Value = Cells(a, ). ...
- python mail
转载一个不错python mail封装 #!/usr/bin/python from email.MIMEText import MIMEText from email.MIMEMultipart i ...