参考网上唯一一发题解 感谢!
题意:
航空公司卖机票。飞机座位是1~n的,卖m张票,m小于等于n,每张票上有三个信息,票号 i,座位号 j,登机入口
k,登机入口指的是从机头进入或者是从机尾进入。
乘客登飞机规则:
1. 乘客按照机票的编号从小到大依次登机。
2. 乘客登飞机时,从票上指定的入口进入,径直走到自己的位置处,如果有人,就看下一个位置有没有人,直到找
到第一个空座位,便入座,如果一直走到头都没有位置,该乘客就会暴走。
航空公司想知道它有多少种印票方式,使得乘客不暴走。其中,票上的座位号可以重复。两种印票方式不同当且仅
当两套票中存在票号为 i 的票,票上的信息不完全一样。
思路:
这个题自己想了好久,还和别人讨论过,但是吧还是不太好想,最后还算是说服了自己吧.大牛们千篇一律得出同样的
公式.
这个题目的一堆条件确实让我感到了蒙蔽, 首先还要考虑进入的方向,编号,还有重叠的,感觉无法下手.
我们可以知道从前门进入一直走到后门没找到位置,和从后门进入一直走到前门没找到位置是等价的.我们可以设置
一个虚拟的位置,这样就构成一个有n+1个位置的环,那么前门后门进入就可以想象成顺时针和逆时针,起点都是那个没
座的位置。那么我们知道所有可能的印票数位2^m * (n+1)^m. 2 ^ m 是由于左右方向.这其中还包含非法的,那么我们
要把非法的减掉,非法的就是1个人没座 2个人没座 3个人没座....m个没座(当然m个实际不存在).那么环上要使某一个
特定位置为空的情况占总情况数的: (n-m+1)/(n+1) 约分得到最后结果为: 2^m *(n+1)^(m-1)*(n+1-m)
其实把公式展开 (2(n+1))^m-2^m*(n+1)^(m-1)*C(m,1).
因为非法的其实就是保证至少有一个人坐在虚拟位置,那么就是C(m,1) 保证至少一人坐在虚拟位置,其余的人随
便坐,那么就有2^m*(n+1)^(m-1)*C(m,1).
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
ll qmod(ll a,ll b)
{
ll res = 1;
while(b)
{
if(b&1)
res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
int main()
{
ll n,m;
scanf("%lld %lld",&n,&m);
ll ans = qmod(2 ,m) * qmod(n + 1,m - 1) % mod * (n- m + 1) % mod;
printf("%lld\n",ans % mod);
return 0;
}