2019.04.03【校内模拟】猎人杀(hunter)(高斯消元)(期望DP)

传送门


解析:

还是一样的绕弯子,这道题求的是概率?不,是概率的期望。

首先所有人编号 − 1 -1 1,这样好处理一些。

f [ i ] [ j ] f[i][j] f[i][j]表示上一个中弹的是第 j j j个人,当前还剩 i i i个人的时候 0 0 0号位置活到最后的概率。

边界状态 f [ 1 ] [ 0 ] = 1 f[1][0]=1 f[1][0]=1

显然状态是分层+层内环状转移。

我们只考虑这一次中弹的人有没有活下来可以得到 f [ n ] [ j ] = 1 2 ( f [ n − 1 ] [ j + k − 1 ] + f [ n ] [ j + k ] ) f[n][j]=\frac{1}2(f[n-1][j+k-1]+f[n][j+k]) f[n][j]=21(f[n1][j+k1]+f[n][j+k])

直接暴力迭代可以发现环长为 l = n gcd ⁡ ( n , k ) l=\frac{n}{\gcd(n,k)} l=gcd(n,k)n

可以发现暴力求解后有线性递推式:

f [ n ] [ j ] = 2 l 2 l − 1 ∑ i = 0 l − 1 f [ n − 1 ] [ ( j + i k − 1 ) % ( n − 1 ) ] 2 i + 1 f[n][j]=\frac{2^l}{2^l-1}\sum_{i=0}^{l-1}\frac{f[n-1][(j+ik-1)\%(n-1)]}{2^{i+1}} f[n][j]=2l12li=0l12i+1f[n1][(j+ik1)%(n1)]

然后就可以 O ( n ) O(n) O(n)做了


代码:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const

using std::cout;
using std::cerr;

cs int mod=1e9+7,inv2=(mod+1)/2;
inline int add(int a,int b){return (a+b>=mod)?a+b-mod:a+b;}
inline int dec(int a,int b){return a<b?a-b+mod:a-b;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline int quickpow(int a,int b,int res=1){
	while(b){
		if(b&1)res=mul(res,a);
		a=mul(a,a);
		b>>=1;
	}
	return res;
}

cs int N=2e3+3;
int p2[N],ip2[N];
int a[N];

inline void solve(int *f,int n,int k){
	int m=std::__gcd(n,k),l=n/m,coef=mul(p2[l],quickpow(p2[l]-1,mod-2));
	for(int re i=0;i<m;++i){
		int s=mul(a[i],inv2),t=1;
		for(int re j=(i+k)%n;j!=i;j=(j+k)%n)
		s=add(s,mul(a[j],ip2[++t]));
		f[i]=mul(s,coef);
		for(int re j=(i+n-k)%n;j!=i;j=(j+n-k)%n)
		f[j]=mul(add(f[(j+k)%n],a[j]),inv2);
	}
}

int n,k,f[N][N];
signed main(){
	std::cin>>n>>k;
	p2[0]=ip2[0]=1;
	for(int re i=1;i<=n;++i)p2[i]=mul(p2[i-1],2),ip2[i]=mul(ip2[i-1],inv2);
	f[1][0]=1;
	for(int re t=2;t<=n;++t){
		for(int re i=1;i<t;++i)a[i]=f[t-1][(i+k-1)%(t-1)];
		solve(f[t],t,k%t);
	}
	cout<<f[n][(k-1)%n];
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值