班服 |
难度级别:C; 运行时间限制:1000ms; 运行空间限制:256000KB; 代码长度限制:2000000B |
试题描述 |
要开运动会了,神犇学校的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种。 |
#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i!=-1;i=next[i])
using namespace std;
int yes;
inline int read() {
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘;
if(c==‘\n‘) yes=1;
return x*f;
}
const int mod=1000000007;
int A[110],f[110][1050];
int main() {
f[0][0]=1;
dwn(T,read(),1) {
memset(A,0,sizeof(A));
int n=read();
rep(i,1,n) {
yes=0;
while(!yes) A[read()]|=1<<i-1;
}
rep(i,1,100) rep(S,0,(1<<n)-1) {
f[i][S]=f[i-1][S];
rep(j,0,n-1) if((A[i]>>j&1)&&(S>>j&1)) (f[i][S]+=f[i-1][S^(1<<j)])%=mod;
}
printf("%d\n",f[100][(1<<n)-1]);
}
return 0;
}