[Codeforces722E] Research Rover (dp+组合数学)
[Codeforces722E] Research Rover (dp+组合数学)
题面
给出一个N*M的方格阵,从(1,1)出发,到(N,M)结束,从(x,y)只能走到(x+1,y)或(x,y+1)。方格阵上还有K个特殊点,初始时给出的分数t每经过一个特殊点就会变成\([\frac{t}{2}]\)。求到(N,M)时得分的期望。保证(1,1)和(N,M)不是特殊点。\(N,M≤100000,\ K≤2000,\ t≤1000000\)
分析
考虑根据特殊点dp.把(1,1)和(n,m)也看作特殊点(但分数不除2),把特殊点按x排序。\(dp[i][j]\)表示经过至少j个特殊点(包括i),到达i的方案数,g(i,j)表示从i点到j点的方案数,
\]
我们从(1,1)走到(n,m) 向上走n次,向右走m次,一共(n+m)次,从n+m次中选出n次向上走,就是方案数
\]
\((dp[u][j-1] - dp[u][j])\)表示经过j-1个特殊点到u的方案数。
为什么我们定义子状态时用的是至少呢?因为从u到i的路径上可能有其他特殊点,导致在u时经过j-1个点,在i时可能就经过j+x (x>=0)个点了,定义为“至少”可以较好的包含这种情况,而需要“正好j个点”的时候只要相减即可。如果我们一开始把子状态定位经过j个点到i的方案数,需要排除中间经过特殊点的情况,容斥起来比较麻烦
最终答案为:
$(C_{n+m}^{m} )^{-1} \times \sum (dp[k][j]-dp[k][j+1]) \times \frac{s}{2^j} $
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxk 3000
#define maxn 100000
#define maxlogs 32
#define mod 1000000007
using namespace std;
inline void qread(int &x){
x=0;
int sign=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') sign=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';
c=getchar();
}
x=x*sign;
}
typedef long long ll;
int n,m,k,s;
int log2s;
struct point{
int x;
int y;
point(){
}
point(int _x,int _y){
x=_x;
y=_y;
}
friend bool operator < (point p,point q){
if(p.x==q.x) return p.y<q.y;
else return p.x<q.x;
}
}a[maxk+5];
inline ll fast_pow(ll x,ll k){
ll ans=1;
while(k){
if(k&1) ans=ans*x%mod;
x=x*x%mod;
k>>=1;
}
return ans;
}
inline ll inv(ll x){
return fast_pow(x,mod-2);
}
ll fact[maxn*2+5],invfact[maxn*2+5];
inline ll C(int n,int m){
// if(m==0||m==n) return 1;
// if(n<m) return 0;
//不要写这几个判断,常数很大
return fact[n]*invfact[n-m]%mod*invfact[m]%mod;
}
void ini_fact(int n){
fact[0]=1;
for(int i=1;i<=n;i++) fact[i]=fact[i-1]*i%mod;
invfact[n]=inv(fact[n]);
for(int i=n-1;i>=0;i--) invfact[i]=invfact[i+1]*(i+1)%mod;
}
inline ll calc(point p,point q){
return C(q.x-p.x+q.y-p.y,q.x-p.x);
}
ll dp[maxk+5][maxlogs+5];//dp[i][j]表示当前到第i个点,经过j个点
int main(){
qread(n);
qread(m);
qread(k);
qread(s);
ini_fact(n+m);
for(int i=1;i<=k;i++){
qread(a[i].x);
qread(a[i].y);
}
sort(a+1,a+1+k);
//加入虚拟点(1,1)(n,m)
if(a[1].x!=1||a[1].y!=1){
s*=2;//多一个点,会多除一次2,所以把s*2来抵消
a[++k]=point(1,1);
}
if(a[k].x!=n||a[k].y!=m) a[++k]=point(n,m);
else s-=s/2;
log2s=log2(s)+1;
sort(a+1,a+1+k);
dp[1][0]=1;
for(int i=2;i<=k;i++){
dp[i][1]=calc(a[1],a[i]);
for(int j=2;j<=log2s;j++){
for(int u=1;u<i;u++){
if(a[u].y<=a[i].y&&a[u].x<=a[i].x){
dp[i][j]+=dp[u][j-1]*calc(a[u],a[i])%mod;
dp[i][j]=(dp[i][j]+mod)%mod;
dp[i][j]-=dp[u][j]*calc(a[u],a[i])%mod;
dp[i][j]=(dp[i][j]+mod)%mod;
}
}
}
}
ll ans=0;
for(int i=1;i<=log2s;i++){
s-=s/2;
ans=(ans+(dp[k][i]-dp[k][i+1]+mod)*s%mod)%mod;
}
ans=ans*inv(calc(a[1],a[k]))%mod;
printf("%I64d\n",ans);
}
[Codeforces722E] Research Rover (dp+组合数学)的更多相关文章
- 【Foreign】Research Rover [DP]
Research Rover Time Limit: 25 Sec Memory Limit: 256 MB Description Input Output 仅一行一个整数表示答案. Sample ...
- CF_229E_Gift_概率DP+组合数学
CF_229E_Gift_概率DP+组合数学 题目描述: 很久很久以前,一位老人和他的妻子住在蔚蓝的海边.有一天,这位老人前去捕鱼,他捉到了一条活着的金鱼.鱼说:“噢,老渔人!我祈求你放我回到海里,这 ...
- codeforces 722E Research Rover
codeforces 722E Research Rover 题意 \(1e5*1e5\)的棋盘中有\(2000\)个坏点,初始给定一个值\(s(1<=s<=1e6)\).从棋盘左上角走到 ...
- [多校联考2019(Round 5 T3)]青青草原的表彰大会(dp+组合数学)
[多校联考2019(Round 5)]青青草原的表彰大会(dp+组合数学) 题面 青青草原上有n 只羊,他们聚集在包包大人的家里,举办一年一度的表彰大会,在这次的表彰大会中,包包大人让羊们按自己的贡献 ...
- CCF 201312-4 有趣的数 (数位DP, 状压DP, 组合数学+暴力枚举, 推公式, 矩阵快速幂)
问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次. 2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前. 3. 最高 ...
- CF_402F dp+组合数学
题目链接:http://codeforces.com/problemset/problem/403/D /**算法分析: 这道题综合的考察了dp背包思想和组合数学 */ #include<bit ...
- 【BZOJ 3294】 3294: [Cqoi2011]放棋子 (DP+组合数学+容斥原理)
3294: [Cqoi2011]放棋子 Description Input 输入第一行为两个整数n, m, c,即行数.列数和棋子的颜色数.第二行包含c个正整数,即每个颜色的棋子数.所有颜色的棋子总数 ...
- Codeforces - 1081C - Colorful Bricks - 简单dp - 组合数学
https://codeforces.com/problemset/problem/1081/C 这道题是不会的,我只会考虑 $k=0$ 和 $k=1$ 的情况. $k=0$ 就是全部同色, $k=1 ...
- Codeforces 840C 题解(DP+组合数学)
题面 传送门:http://codeforces.com/problemset/problem/840/C C. On the Bench time limit per test2 seconds m ...
随机推荐
- ideamaven版的MBG逆向工程
一.简介 简称MBG,是一个专门为MyBatis框架使用者定制的代码生成器,可以快速的根据表生成对应的映射文件,接口,以及bean类. 支持基本的增删改查,以及QBC风格的条件查询. 但是表连接.存储 ...
- How to Add Memory, vCPU, Hard Disk to Linux KVM Virtual Machine
ref: https://www.thegeekstuff.com/2015/02/add-memory-cpu-disk-to-kvm-vm/ In our previous article of ...
- linux--基础知识3
#linux虚拟终端切换 ctrl+alt+F(1-6) 总共支持六个终端切换 #mkdir /root/boot/目录 在指定路径下新建目录 #touch /目录/文件名 在指定目录创建文件 ...
- [BJWC2010]严格次小生成树(LCA,最小生成树)
[BJWC2010]严格次小生成树 题目描述 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图 ...
- 通过反射获取方法的参数名称(JDK8以上支持)
方法的参数名,在很多时候我们是需要反射得到的.但是在java8之前,代码编译为class文件后,方法参数的类型是固定的,但参数名称却丢失了,这和动态语言严重依赖参数名称形成了鲜明对比.(java是静态 ...
- 【leetcode】1073. Adding Two Negabinary Numbers
题目如下: Given two numbers arr1 and arr2 in base -2, return the result of adding them together. Each nu ...
- LeetCode--052--N皇后II(java)
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击. 上图为 8 皇后问题的一种解法. 给定一个整数 n,返回 n 皇后不同的解决方案的数量. 示例: 输入 ...
- OC + RAC (八) 查看信号状态和跳过信号
-(void)_test9{ /// RACCommand又叫命令 是用来收发数据的 监听按钮点击,网络请求.... RACCommand * command = [[RACCommand alloc ...
- springboot版本依赖
springboot2.x及以后依赖于jdk1.8及以上. 如图:
- webApp 页面布局
1. 流式布局 概念:流式布局是页面元素宽度按照屏幕分辨率进行适配调整,但是整体布局不变. 设计方法:布局都是通过百分比来定义宽度,但是高度大都是用px固定的. 弊端: 虽然可以让各种屏幕适配,但是显 ...