Newcoder 111 B.托米看電影(狀壓)
Description
有一天, 個女孩子一起去托米家的電影院看電影。她們都訂了同一排的票,訂完票後還剩下一些時間,她們就去附近購物了,當她們回來的時候,電影已經開始了。門口檢票的托米讓她們一個接一個找到位置並坐下。
但是,列印電影票的機器壞了。打印出來的座位號不是連續的數字,而是 到 之間的隨機整數(說明有重複的),其中 是她們行中的座位總數。
當一個女孩走進一排座位時,座位號從 開始,當她走到她的票號位置上時。如果此時這個座位是空的,她就坐下來。如果它已經被佔用,她繼續沿著相同的方向走(不能回頭),直到她找到第一個空位,然後坐在那裡。
所以,有些女孩可能會在沒有找到坐下的地方的情況下被排到最後,然後沒有位置坐。
現在給你數字 和 。
假設每個女孩的票數都在 到 之間,包括 和 之間的數字。每個數字都是隨機抽取的,並且抽取是獨立的。
當第一個女孩開始尋找她的座位時,也假定整行都是空的。
請你計算至少有一個女孩遭受迎面而來的悲慘命運的概率。
Input
輸入的第一行包含一個整數 ,表示指定測試用例的數量。
每個測試用例前面都有一個空白行。
每個測試用例由包含兩個整數 和 的單行組成
Output
對於每個測試用例輸出其概率,用最簡分式表示。
Sample Input
3
1 10
2 3
3 3
Sample Output
0/1
1/9
11/27
Solution
狀壓
,以
表示
個人,還有
狀態的座位沒有被選,最終至少有一個女孩沒有座位的方案數,列舉第
個女孩的票號
,如果
中第
個位置為
,那麼直接轉移
如果
中第
個位置為
,那麼考慮第
個位置之後是否還有
,如果沒有
說明第
個女孩沒有座位,剩下
個女孩隨便選,直接有轉移
如果
位置之後有一個位置
為
,那麼第
個女孩只能坐在第
個位置,此時又轉移
記憶化搜尋即可,答案即為
,時間複雜度
Code
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
int T,n,k;
ll dp[11][(1<<10)+5],f[11];
ll gcd(ll a,ll b)
{
return b?gcd(b,a%b):a;
}
ll dfs(int n,int S)
{
if(dp[n][S]!=-1)return dp[n][S];
if(n==0)return dp[n][S]=0;
if(S==0)return dp[n][S]=f[n];
dp[n][S]=0;
for(int i=0;i<k;i++)
if(!((S>>i)&1))
{
int j=i+1;
for(;j<k;j++)
if((S>>j)&1)break;
if(j<k)dp[n][S]+=dfs(n-1,S^(1<<j));
else dp[n][S]+=f[n-1];
}
else dp[n][S]+=dfs(n-1,S^(1<<i));
return dp[n][S];
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&k);
f[0]=1;
for(int i=1;i<=n;i++)f[i]=f[i-1]*k;//k^i
int K=1<<k;
memset(dp,-1,sizeof(dp));
ll p=dfs(n,K-1),q=f[n];
ll g=gcd(p,q);
printf("%lld/%lld\n",p/g,q/g);
}
return 0;
}