首页 > 代码库 > 【Foreign】Research Rover [DP]

【Foreign】Research Rover [DP]

Research Rover

Time Limit: 25 Sec  Memory Limit: 256 MB

Description

  技术分享

Input

  技术分享

Output

  仅一行一个整数表示答案。

Sample Input

  3 3 2 11
  2 1
  2 3

Sample Output

  333333342

  技术分享

HINT

  技术分享

Main idea

  从(1,1)走到(n,m),每次可以向右或向下走一步,有K个特殊点,初始有一个权S,每经过一个特殊点S=(S+1)/2,询问到(n,m)的S的期望。

Source

  我们显然想到了DP,研究一下题目,发现可以按照到达目标之后S的值分类,显然S的取值只和经过特殊点的个数相关。并且由于每经过一个特殊点,S的值就会/2,那么显然只有log2(S)种取值,所以我们可以去考虑一个O(K^2log(S))的做法。

  首先,从起点走到终点的总方案数是:技术分享,我们可以将终点也当做特殊点,那么就可以令 f[i][j] 表示到了第 i 个目标点,经过 j 个目标点的方案数

  那么我们可以考虑容斥技术分享

  那么写成表达式也就是:

技术分享

  其中:技术分享,计算方法显然和计算总方案一样,运用组合数。(组合数计算的时候求一下乘法逆元阶乘逆元即可)

  这样的话就可以算出到终点经过 i 个特殊点的方案、乘上对应的S的值、然后计算一下、再乘上总方案的乘法逆元就是答案了。

  效率就是O(k^2 * log(S)),就可以解决这道题啦。\(≧▽≦)/

Code

技术分享
  1 #include<iostream>    2 #include<algorithm>    3 #include<cstdio>    4 #include<cstring>    5 #include<cstdlib>    6 #include<cmath>    7 using namespace std;  8 typedef long long s64;  9 const int ONE = 200005; 10 const int INF = 214783640; 11 const int MOD = 1e9+7; 12  13 int Mod = MOD; 14 int n,m,K,S; 15 int f[ONE][30]; 16 int Jc[ONE],inv[ONE]; 17 int A[30],a_num; 18 int Up; 19  20 struct power 21 { 22         int x,y; 23 }a[ONE]; 24  25 int cmp(const power &a,const power &b) 26 { 27         return a.x+a.y < b.x+b.y; 28 } 29  30 int get() 31 {  32         int res,Q=1;    char c; 33         while( (c=getchar())<48 || c>57) 34         if(c==-)Q=-1; 35         if(Q) res=c-48;  36         while((c=getchar())>=48 && c<=57)  37         res=res*10+c-48;  38         return res*Q;  39 } 40  41 namespace D 42 { 43         int Quickpow(int a,int b) 44         { 45             int res=1; 46             while(b) 47             { 48                 if(b&1) res=(s64)res*a%MOD; 49                 a=(s64)a*a%MOD; 50                 b>>=1; 51             } 52             return res; 53         } 54      55         void Deal_Jc(int k) 56         { 57             Jc[0]=1; 58             for(int i=1;i<=k;i++) Jc[i] = (s64)Jc[i-1]*i%MOD; 59         } 60          61         void Deal_inv(int k) 62         { 63             inv[0]=1;    inv[k] = Quickpow(Jc[k],MOD-2); 64             for(int i=k-1;i>=1;i--) inv[i] = (s64)inv[i+1]*(i+1)%MOD; 65         } 66          67         void pre(int k) 68         { 69             Deal_Jc(k);    Deal_inv(k); 70         } 71 } 72 int C(int n,int m) 73 { 74         return (s64)Jc[n]*inv[m]%MOD*inv[n-m]%MOD;  75 } 76   77 int ways(int i,int j) 78 { 79         return C(a[j].x+a[j].y-a[i].x-a[i].y, a[j].x-a[i].x); 80 } 81  82 void Moit(int &a) 83 { 84         if(a<0) a+=MOD; 85         if(a>MOD) a-=MOD; 86 } 87  88 int main() 89 { 90         n=get();    m=get();    K=get();    S=get(); 91              92         A[0]=S;    for(a_num=1;a_num<=24;a_num++) S=(S+1)/2, A[a_num]=S; 93         D::pre(n+m); 94          95            for(int i=1;i<=K;i++) 96         { 97             a[i].x=get();    a[i].y=get(); 98         } 99         a[++K].x = n;    a[K].y = m;100         sort(a+1,a+K+1,cmp);101         102         for(int i=1;i<=K;i++)103         {104             for(int j=0;j<a_num;j++)105             {106                 f[i][j] = C(a[i].x+a[i].y-2,a[i].x-1);107                 for(int k=1;k<=i-1;k++)108                 {109                     if(a[k].x <= a[i].x && a[k].y <= a[i].y)110                     f[i][j] -= (s64)f[k][j] * ways(k,i) % MOD,111                     Moit(f[i][j]);112                 }113                 114                 for(int k=0;k<=j-1;k++)115                     f[i][j] -= f[i][k], Moit(f[i][j]);116             }117         }118         119         int All = C(n+m-2,n-1);120         121         for(int i=0;i<a_num;i++)122         {123             Up = (Up + (s64)f[K][i]*A[i]) % MOD;124             All -= f[K][i]; Moit(All);125         }126         127         Up = Up + All;    Moit(Up);128         129         printf("%d",(s64)Up * D::Quickpow(C(n+m-2,n-1),MOD-2) % MOD);130 }
View Code

 

【Foreign】Research Rover [DP]