模擬賽 班服

班服
 (shirt.pas/.c/.cpp)
時間限制:1s;內存限制 128MB
題目描述:
要開運動會了,神犇學校的n個班級要選班服,班服共有100種樣式,編號1~100。如今每一個班都挑出了一些樣式待選,每一個班最多有100個待選的樣式。要求每一個班最終選定一種樣式做爲班服,且該班的樣式不能與其餘班級的相同,求全部可能方案的總數,因爲方案總數可能很大,因此要求輸出mod 1000000007後的答案。
輸入描述:
共有T組數據。
對於每組數據,第一行爲一個整數n,表示有n個班級。
2~n+1行,每行有最多100個數字,表示第i-1班待選班服的編號。
輸出描述:
對於每組數據,輸出方案總數 mod 1000000007後的答案。
樣例輸入:
2
3
5 100 1
2
5 100
2
3 5
8 100
樣例輸出:
4
4
數據範圍:
對於30%的數據,1<=T<=3, 1<=n<=3,每班待選樣式不超過10種。
對於50%的數據,1<=T<=5, 1<=n<=5,每班待選樣式不超過50種。
對於100%的數據,1<=T<=10, 1<=n<=10,每班待選樣式不超過100種。
題目

 

芒果君:考試的時候徹底沒看出來這題是狀壓DP,還想了很久的組合數學……最後只能打暴力QAQios

這道題的n很小(10),能夠說是一種提示。那咱們能夠用二進制來表示n被選擇的狀態,末狀態是(1<<n)-1。固然咱們也要處理班級與服裝的關係,在讀入時讓服裝來存儲班級的信息才能方便轉移。方程和去年noip憤怒的小鳥差很少,只要把狀態不斷填充就能夠了。ide

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cmath>
 6 #include<vector>
 7 #define ll long long
 8 #define eps 1e-8
 9 using namespace std;
10 const int mod=1e9+7;
11 int T,n,x,mp[110][110],f[110][1<<11];
12 int main()
13 {
14     scanf("%d",&T);
15     while(T--){
16         memset(mp,0,sizeof(mp));
17         memset(f,0,sizeof(f));
18         scanf("%d",&n);
19         for(int i=1;i<=n;++i){
20             while(1){
21                 scanf("%d",&x);
22                 mp[x][++mp[x][0]]=i;
23                 char ch=getchar();
24                 if(ch=='\n') break;
25             }
26         }
27         f[0][0]=1;
28         for(int i=1;i<=100;++i)
29             for(int j=0;j<(1<<n);++j){
30                 f[i][j]+=f[i-1][j];
31                 for(int k=1;k<=mp[i][0];++k)
32                     if(j&(1<<mp[i][k]-1))
33                         (f[i][j]+=f[i-1][j-(1<<mp[i][k]-1)])%=mod;
34             }
35         printf("%d\n",f[100][(1<<n)-1]);
36     }
37     return 0;
38 }
相關文章
相關標籤/搜索