题目描述:https://www.luogu.org/problemnew/show/CF838D(有翻译)
(为什么博客园把我刚写的给吞了……orz)
这题当初看的十分懵逼,不过听了肖大佬的做法还是很清楚的。
因为乘客们可以从双向进入,然后乘客只会看给自己安排的座位和后面的空座位,所以我们不如直接新建一个虚拟座位,把这个序列变成一个环。乘客在找不到真实座位中找不到座位了,自然就会坐到虚拟位置上。因此,如果一个方案中虚拟位置被坐了说明不合法,否则就合法。
虚拟位置与其他位置一样是一个普通的座位,对于m个人来说,其没有被占据的概率为(n+1-m) / (n+1)。而所有的安排数是(2*(n+1)) ^ m,他们的乘积整理出来就是结果,即2^m * (n+1) ^ (m-1) * (n+1-m)
代码很短。(数学题大都难想……不过代码却可能很短)
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cmath> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar(' ') using namespace std; typedef long long ll; const ll mod = 1e9+7; const int M = 300005; ll read() { ll ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } ll n,m; ll qpow(ll a,ll b) { ll q = 1; while(b) { if(b&1) q *= a,q %= mod; a *= a,a %= mod; b >>= 1; } return q; } int main() { n = read(),m = read(); printf("%lld ",qpow(2,m) * qpow(n+1,m-1) % mod * (n+1-m) % mod); return 0; }