[提交][状态][博客][加入收藏]
有一位流浪者正在一个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,表示一个障碍点,保证一个障碍点不会出现多次。起点与终点可能也会是障碍点。
仅一行一个整数表示答案。
样例1输入
3 3 2 11
2 1
2 3
样例2输入
1 6 2 15
1 1
1 5
样例1输出
333333342
样例2输出
4
样例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
ExfJoe
题解:
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
#include
#include
#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>=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;ji;--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<