题目

传送门

解法

自闭了。

我们将飞机变成 \(\mathtt{UFO}\),前后门就连在一起合成一个点 \(n+1\)。这就是长度为 \(n+1\) 的环,前后门就变成了顺逆时针。需要注意的是,\(n+1\) 与其它点完全一样,所以到了 \(n+1\) 如果已占就会沿先前方向继续走。

每个人的目标座位和前后门 来分析总方案数:\((2\times (n+1))^m\)

如何删掉不合法的方案?因为用登机方案来判断最终座位以及是否合法非常麻烦,我们另辟蹊径。首先我们知道,坐了 \(n+1\) 这个位置就不合法(注意这不是目标态而是最终态)。在分析总方案数时,我们将所有的点视作同样的,而且到了 \(n+1\) 如果已占就会沿先前方向继续走,感性可得所有座位被坐的概率相同。又因为一共坐 \(m\) 个座位,设每个座位被坐的概率为 \(p\),有 \(p\times (n+1)=m\),则 \(p=\frac{m}{n+1}\)。那么每个座位不被坐的概率为 \(\frac{n+1-m}{n+1}\)

所以答案就是 \((2\times (n+1))^m\times \frac{n+1-m}{n+1}\)

最后分析一下一种看似会被多算的情况:目标位置为 \(n+1\)。这样最终 \(n+1\) 一定会被坐,所以又被减去了。

代码

#include <cstdio>

#define rep(i,_l,_r) for(register signed i=(_l),_end=(_r);i<=_end;++i)
#define fep(i,_l,_r) for(register signed i=(_l),_end=(_r);i>=_end;--i)
#define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
#define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
#define print(x,y) write(x),putchar(y)

template <class T> inline T read(const T sample) {
    T x=0; int f=1; char s;
    while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
    while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
    return x*f;
}
template <class T> inline void write(const T x) {
    if(x<0) return (void) (putchar('-'),write(-x));
    if(x>9) write(x/10);
    putchar(x%10^48);
}
template <class T> inline T Max(const T x,const T y) {if(x>y) return x; return y;}
template <class T> inline T Min(const T x,const T y) {if(x<y) return x; return y;}
template <class T> inline T fab(const T x) {return x>0?x:-x;}
template <class T> inline T gcd(const T x,const T y) {return y?gcd(y,x%y):x;}
template <class T> inline T lcm(const T x,const T y) {return x/gcd(x,y)*y;}

const int mod=1e9+7;

int qkpow(int x,int y) {
	int r=1;
	while(y) {
		if(y&1) r=1ll*r*x%mod;
		x=1ll*x*x%mod; y>>=1;
	}
	return r;
}

int main() {
	int n=read(9),m=read(9);
	print(1ll*qkpow(2*(n+1),m)*(n+1-m)%mod*qkpow(n+1,mod-2)%mod,'\n');
	return 0;
}
posted on 2021-02-15 19:51  Oxide  阅读(44)  评论(0编辑  收藏  举报