3130: 流浪者(rover)
阿新 • • 發佈:2018-12-19
題目描述
有一位流浪者正在一個n∗mn∗m的網格圖上流浪。初始時流浪者擁有SS點體力值。
流浪者會從(1,1)(1,1)走向(n,m)(n,m),並且他只會向下走((x,y)→(x+1,y))((x,y)→(x+1,y))或是往右走((x,y)→(x,y+1))((x,y)→(x,y+1)),在所有可行的路線中他會隨機選擇一條。
網路圖中還有KK個障礙點。若流浪者當前體力值為SS,則他經過一個障礙點後體力值會變為⌈S2⌉⌈S2⌉。
現在請你求出,流浪者到達(n,mn,m)時他體力值的期望是多少。
若答案為abab,則你輸出abab在模109+7109+7意義下的值即可。
輸入
第一行四個整數n,m,K,Sn,m,K,S, 意義見題目描述。
接下來K行每行兩個整數Xi,YiXi,Yi,表示一個障礙點,保證一個障礙點不會出現多次。起點與終點可能也會是障礙點。
輸出
僅一行一個整數表示答案。
樣例輸入
<span style="color:#333333"><span style="color:#333333">樣例1輸入
3 3 2 11
2 1
2 3
樣例2輸入
1 6 2 15
1 1
1 5</span></span>
樣例輸出
<span style="color:#333333"><span style="color:#333333">樣例1輸出 333333342 樣例2輸出 4</span></span>
提示
樣例1解釋
共有6種合法路徑,這裡不一一列出。
16∗(6+6+11+3+6+6)=19316∗(6+6+11+3+6+6)=193
約定
30%的資料:n,m≤10n,m≤10
50%的資料:n,m≤1000n,m≤1000
1000%的資料:1≤n,m≤105,0≤K≤min(n∗m,2000),1≤S≤1061≤n,m≤105,0≤K≤min(n∗m,2000),1≤S≤106
來源
題解:
dp,f[i][j]表示從第i個特殊點出發經歷正好j個特殊點到達(n,m)的方案數,可是這個dp不好轉移。
所以我們再用g[i][j]表示至多走過j個點的方案數,這樣f[i][j]=g[i][j]-g[i][j-1]。
那麼g[i[][j]也很好轉移,列舉下一個經過的特殊點即可轉移。
#include<iostream>
#include<cstdio>
#include<algorithm>
#define mod 1000000007
using namespace std;
int n,m,k,S,cnt,b[200005];long long jc[200005],ny[200005],g[2005][30],ans;
struct Node{int x,y;}s[2005];
bool cmp(Node t1,Node t2){return t1.x<t2.x||(t1.x==t2.x&&t1.y<t2.y);}
long long ksm(long long x,long long y)
{
long long sum=1;
while(y)
{
if(y&1)sum=sum*x%mod;
x=x*x%mod;y>>=1;
}
return sum;
}
long long C(int x,int y){return jc[x]*ny[y]%mod*ny[x-y]%mod;}
int main()
{
scanf("%d%d%d%d",&n,&m,&k,&S);
for(int i=1;i<=k;++i)scanf("%d%d",&s[i].x,&s[i].y);
sort(s+1,s+1+k,cmp);
jc[0]=1;
for(int i=1;i<=2e5;++i)jc[i]=jc[i-1]*i%mod;
ny[200000]=ksm(jc[200000],mod-2);
for(int i=2e5;i;--i)ny[i-1]=ny[i]*i%mod;
b[0]=S;
while(S!=1)b[++cnt]=(S+1)/2,S=(S+1)/2;
s[0].x=1;s[0].y=1;
for(int i=k;~i;--i)
{
for(int j=0;j<cnt;++j)
{
g[i][j]=C(n-s[i].x+m-s[i].y,n-s[i].x);
for(int t=k;t>i;--t)
if(s[i].y<=s[t].y)
g[i][j]=((g[i][j]-g[t][j]*C(s[t].x-s[i].x+s[t].y-s[i].y,s[t].x-s[i].x)%mod)%mod+mod)%mod;
}
g[i][cnt]=C(n-s[i].x+m-s[i].y,n-s[i].x);
for(int j=cnt;j;--j)g[i][j]=((g[i][j]-g[i][j-1])%mod+mod)%mod;
}
for(int i=0;i<=cnt;++i)ans=(ans+g[0][i]*(long long)b[i]%mod)%mod;
ans=ans*ksm(C(n+m-2,n-1),mod-2)%mod;
cout<<ans;
}