当前位置: 首页 > 工具软件 > J!Research > 使用案例 >

Codeforces722E Research Rover dp+逆元+前缀和

夏朗
2023-12-01

题目链接:传送门

Research rover finally reached the surface of Mars and is ready to complete its mission. Unfortunately, due to the mistake in the navigation system design, the rover is located in the wrong place.

The rover will operate on the grid consisting of n rows and m columns. We will define as (r, c) the cell located in the row r and column c. From each cell the rover is able to move to any cell that share a side with the current one.

The rover is currently located at cell (1, 1) and has to move to the cell (n, m). It will randomly follow some shortest path between these two cells. Each possible way is chosen equiprobably.

The cargo section of the rover contains the battery required to conduct the research. Initially, the battery charge is equal to s units of energy.

Some of the cells contain anomaly. Each time the rover gets to the cell with anomaly, the battery looses half of its charge rounded down. Formally, if the charge was equal to x before the rover gets to the cell with anomaly, the charge will change to .

While the rover picks a random shortest path to proceed, compute the expected value of the battery charge after it reaches cell (n, m). If the cells (1, 1) and (n, m) contain anomaly, they also affect the charge of the battery.

Input
The first line of the input contains four integers n , m , k n, m, k n,m,k and s s s ( 1   ≤   n ,   m   ≤   100   000 , 0   ≤   k   ≤   2000 , 1   ≤   s   ≤   1   000   000 ) (1 ≤ n, m ≤ 100 000, 0 ≤ k ≤ 2000, 1 ≤ s ≤ 1 000 000) (1n,m100000,0k2000,1s1000000) — the number of rows and columns of the field, the number of cells with anomaly and the initial charge of the battery respectively.

The follow k k k lines containing two integers r i r_i ri and c i c_i ci ( 1   ≤   r i   ≤   n , 1   ≤   c i   ≤   m ) (1 ≤ r_i ≤ n, 1 ≤ c_i ≤ m) (1rin,1cim) — coordinates of the cells, containing anomaly. It’s guaranteed that each cell appears in this list no more than once.

Output
The answer can always be represented as an irreducible fraction P Q \frac{P}{Q} QP. Print the only integer P ⋅ Q − 1 P·Q^{-1} PQ1 modulo 1 0 9 + 7 10^9+7 109+7.

需要点亮的技能:
1. O ( n ) 1.O(n) 1.O(n)求阶乘的逆元。
2. 2. 2.熟练运用组合数。
3. d p 3.dp 3.dp技巧。

首先yy出这是个dp。
把题目给出的特殊点排序,以 x x x坐标为第一关键字, y y y坐标为第二关键字。
发现 n , m n,m n,m珂以达到 1 0 5 10^5 105级别,因此不考虑将其设计成子状态的某一维。
发现 k k k比较小,考虑让 k k k作为子状态的一维。
d p [ i ] [ j ] dp[i][j] dp[i][j]表示从第 i i i个特殊点,恰好经过 j j j个特殊点走到 ( n , m ) (n,m) (n,m)的情况数。
d [ i ] [ j ] d[i][j] d[i][j]表示从第 i i i个特殊点走到第 j j j个特殊点的方案数。
显然 d [ i ] [ j ] = C x [ j ] − x [ i ] + y [ j ] − y [ i ] x [ j ] − x [ i ] d[i][j]=C_{x[j]-x[i]+y[j]-y[i]}^{x[j]-x[i]} d[i][j]=Cx[j]x[i]+y[j]y[i]x[j]x[i]

转移 d p [ i ] [ j ] dp[i][j] dp[i][j]时注意到恰好走 j j j个特殊点不好转移,
于是令 f [ i ] [ j ] f[i][j] f[i][j]表示从第 i i i个特殊点,至多经过 j j j个特殊点走到 ( n , m ) (n,m) (n,m)的方案数。
然后珂以利用容斥原理(所有的情况 − - 经过特殊点数超过 j j j的情况)转移:
枚举 i , j i,j i,j和经过的一个特殊点 l l l,排除掉既经过 l l l,又除 l l l外经过 j j j个特殊点的情况数。
故珂以写出代码:

f[i][j]=f[i][len];
for(re l=k; l>i; l--) {
	if(w[i].y<=w[l].y) {
		f[i][j]=(f[i][j]-dp[l][j]*d[i][l]%mod+mod)%mod;
	}
}

珂以看出 f [ i ] [ j ] f[i][j] f[i][j] d p [ i ] [ j ] dp[i][j] dp[i][j]的前缀和,
然后 d p [ i ] [ j ] dp[i][j] dp[i][j]就珂以通过 f [ i ] [ j ] f[i][j] f[i][j]求出。

放上毒瘤无比的代码:

#include<stdio.h>
#include<cstring>
#include<algorithm>
#define re register int
using namespace std;
typedef long long ll;
inline char getc() {
    static char buf[262145],*fs,*ft;
    return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<18,stdin)),fs==ft)?EOF:*fs++;
}
int read() {
	re x=0,f=1;
	char ch=getc();
	while(ch<'0' || ch>'9') {
		if(ch=='-')	f=-1;
		ch=getc();
	}
	while(ch>='0' && ch<='9') {
		x=10*x+ch-'0';
		ch=getc();
	}
	return x*f;
}
ll fastpow(ll b,ll p,ll k) {
	ll ans=1;
	while(p) {
		if(p&1)	ans=ans*b%k;
		b=b*b%k;
		p>>=1;
	}
	return ans;
}
const int Size=2005;
const int Maxn=200005;
const ll mod=1e9+7;
int n,m,k,s,a[Size];
ll d[Size][Size],f[Size][21],dp[Size][21];
ll fac[Maxn],inv[Maxn];
struct node {
	int x,y;
} w[Size];
inline bool comp(node mhy,node ypy) {
	if(mhy.x!=ypy.x)	return mhy.x<ypy.x;
	return mhy.y<ypy.y;
}
inline ll C(int n,int m) {
	return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
inline ll Inv(ll x) {
	return fastpow(x,mod-2,mod);
}
int main() {
	n=read();
	m=read();
	k=read();
	s=read();
	fac[0]=1;
	for(re i=1; i<=n+m; i++) {
		fac[i]=fac[i-1]*i%mod;
	}
	inv[n+m]=Inv(fac[n+m]);
	for(re i=n+m-1; i>=0; i--) {
		inv[i]=inv[i+1]*(i+1)%mod;
	}
	for(re i=1; i<=k; i++) {
		w[i].x=read();
		w[i].y=read();
	}
	sort(w+1,w+1+k,comp);
	w[0].x=w[0].y=1;
	for(re i=0; i<=k; i++) {
		d[i][i]=1;
		for(re j=i+1; j<=k; j++) {
			if(w[i].y<=w[j].y) {
				d[i][j]=C(w[j].y-w[i].y+w[j].x-w[i].x,w[j].x-w[i].x);
			}
		}
	}
	a[0]=s;
	int len=0;
	while(s!=1) {
		a[++len]=s=(s+1)>>1;
	}
	for(re i=k; i>=0; i--) {
		f[i][len]=C(n+m-w[i].x-w[i].y,n-w[i].x);
		for(re j=0; j<len; j++) {
			f[i][j]=f[i][len];
			for(re l=k; l>i; l--) {
				if(w[i].y<=w[l].y) {
					f[i][j]=(f[i][j]-dp[l][j]*d[i][l]%mod+mod)%mod;
				}
			}
		}
		for(re j=len; j; j--) {
			dp[i][j]=(f[i][j]-f[i][j-1]+mod)%mod;
		}
		dp[i][0]=f[i][0];
	}
	ll ans=0;
	for(re i=0; i<=len; i++) {
		dp[0][i]=(dp[0][i]%mod+mod)%mod;
		ans=(ans+dp[0][i]*a[i]%mod)%mod;
	}
	ans=ans*Inv(C(n+m-2,n-1))%mod;
	printf("%lld",ans);
	return 0;
}
 类似资料: