[codeforces722E] Research Rover
2016-10-27 17:22
127 查看
题目大意
有一个n*m的网格图,你要从(1,1)走到(n,m),每一步可以向右(或向下)走。你最开始有s点能量,然而有k个障碍点,每到达一个障碍点,你的能量会变成⌈x2⌉。问走到(n,m)时你最终能量的期望。假设它是PQ,输出P∗Q−1模109+7的逆元。数据范围
n,m≤100000 k≤2000 1≤s≤1000000分析
首先可以发现,s最终变成1后,一直变化都是1,所以s最多只有logs个取值。把障碍点排序,这是一定要的。并且把(n,m)也看成障碍点
然后可以设f[i][j]表示走到第j个障碍点,经过i个障碍点的答案。我们发现如果求每个点两两之间不经过任何其它障碍点的答案较难,所以可以考虑容斥。
设g[i][j],j和上面一样,i表示经过至少i个障碍点。容易求出f[0]、g[0]的值。然后对于i>0转移如下:
g[i][j]=∑f[i−1][k]∗Ways[k][j]
f[i][j]=g[i][j]−∑f[i][k]∗Ways[k][j]
其中Ways[i][j]表示i到j的方案数,这个组合数算一下就好了。
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define fi first #define se second using namespace std; const int maxs=2005,maxn=200005,mo=1e9+7,N=22; typedef long long LL; typedef double db; typedef pair<int,int> PII; int n,m,k,s,M,Energy ,f [maxs],g [maxs],All[maxs][maxs],Fac[maxn],Fac_Inv[maxn],Inv[maxn],ans; PII Point[maxs]; char c; int read() { for (c=getchar();c<'0' || c>'9';c=getchar()); int x=c-48; for (c=getchar();c>='0' && c<='9';c=getchar()) x=x*10+c-48; return x; } bool cmp(PII a,PII b) { return a.fi<b.fi || a.fi==b.fi && a.se<b.se; } void Init() { n=read(); m=read(); k=read(); s=read(); for (int i=1;i<=k;i++) { Point[i].fi=read()-1; Point[i].se=read()-1; } sort(Point+1,Point+k+1,cmp); Point[++k].fi=n-1; Point[k].se=m-1; Point[0].fi=Point[0].se=0; Fac[0]=Fac_Inv[0]=Fac[1]=Fac_Inv[1]=Inv[1]=1; for (int i=2;i<=n+m;i++) { Fac[i]=(LL)Fac[i-1]*i%mo; Inv[i]=(LL)Inv[mo%i]*(mo-mo/i)%mo; Fac_Inv[i]=(LL)Fac_Inv[i-1]*Inv[i]%mo; } Energy[0]=s; while (s>1) Energy[++M]=s=ceil((db)s/2); } int Comb(int N,int M) { return (LL)Fac *Fac_Inv[M]%mo*Fac_Inv[N-M]%mo; } void Work() { for (int i=1;i<=k;i++) { f[0][i]=g[0][i]=Comb(Point[i].fi+Point[i].se,Point[i].fi); for (int j=1;j<i;j++) if (Point[i].se>=Point[j].se) { All[j][i]=Comb(Point[i].fi-Point[j].fi+Point[i].se-Point[j].se,Point[i].fi-Point[j].fi); f[0][i]=(f[0][i]+mo-(LL)f[0][j]*All[j][i]%mo)%mo; } } for (int i=1;i<=M;i++) { for (int j=i+1;j<=k;j++) { for (int x=i;x<j;x++) if (Point[x].se<=Point[j].se) g[i][j]=(g[i][j]+(LL)f[i-1][x]*All[x][j])%mo; f[i][j]=g[i][j]; for (int x=i;x<j;x++) if (Point[x].se<=Point[j].se) f[i][j]=(f[i][j]+mo-(LL)f[i][x]*All[x][j]%mo)%mo; } } ans=0; for (int i=0;i<M;i++) ans=(ans+(LL)Energy[i]*f[i][k]%mo)%mo; ans=(ans+g[M][k])%mo; ans=(LL)ans*Fac[n-1]%mo*Fac[m-1]%mo*Fac_Inv[n+m-2]%mo; printf("%d\n",ans); } int main() { Init(); Work(); return 0; }
相关文章推荐
- codeforces 722E Research Rover
- Intel Code Challenge Elimination Round (Div.1 + Div.2, combined)E. Research Rover (容斥Lucas)
- 【Foreign】Research Rover [DP]
- industry对academic architecture research的看法
- My feeling during research
- [copy] FtpWebRequest Behavior Research
- 垂直搜索&分类网站类文章 iResearch.cn/史岩的文章
- How to do research!
- Computer Applications in Pharmaceutical Research and Development
- Metasploit Toolkit for Penetration Testing, Exploit Development, and Vulnerability Research
- ATSAM9260 NORFLASH Boot solution research
- Why do we research on OSGi?为何我们学习OSGi?
- Links of Manufacutring Engineering Research Institutes
- [转]: 学会用GOOGLE做research
- RTP Stack Research
- 各大公司(Google,Microsoft,Baidu, Microsoft Research Asia etc.)
- You and Your Research
- 学会用GOOGLE做research
- hdu 1164 Eddy's research I (数论)
- How To Do Research In the MIT AI Lab