题意:复习功课,有n章,每天复习1章,但有m个要求,第i章不能在第j天复习,问有多少种复习方式?
#include<iostream>
#include<cstdio>
#include<string.h>
#include<math.h>
using namespace std;
typedef long long LL;
#define MOD 55566677
#define N 55
LL f[N],res;
int n,m,vis1[N],vis2[N],a[N][N],ban[N][N];
void inint()
{
f[0]=1;
for(int i=1; i<N; i++)
f[i]=(f[i-1]*i)%MOD;
}
void dfs(int i,int num) //第i个禁位,选num个禁位
{
if(i>m)
{
if(num&1) res=((res-f[n-num])%MOD+MOD)%MOD;
else res=(res+f[n-num])%MOD;
return;
}
dfs(i+1,num); //第i个禁位不选
if((!vis1[a[i][0]])&&(!vis2[a[i][1]])) //选第i个禁位
{
vis1[a[i][0]]=vis2[a[i][1]]=1;
dfs(i+1,num+1);
vis1[a[i][0]]=vis2[a[i][1]]=0;
}
}
int main()
{
int i,j,d,c;
inint();
while(~scanf("%d%d",&n,&m))
{
memset(vis1,0,sizeof(vis1));
memset(vis2,0,sizeof(vis2));
memset(ban,0,sizeof(ban));
for(i=1; i<=m; i++)
{
scanf("%d%d",&a[i][0],&a[i][1]);
if(ban[a[i][0]][a[i][1]])
{
i--;
m--;
}
else ban[a[i][0]][a[i][1]]=1;
}
res=0;
dfs(1,0);
res=(res%MOD+MOD)%MOD;
printf("%lld\n",res);
}
return 0 ;
}