The Review Plan I
题意: 你要用n 天复习 n 门课, 每天一门,但是有限制条件,某一天不能复习某几门课。
禁位排列的模板题,看了好长时间别人的博客,看懂了棋子多项式,但是代码看不懂(orz)
定理:
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#define MOD 55566677
#define N 55
using namespace std;
typedef long long ll;
ll f[N],res;
int n,m;
int a[N][N];
int vis1[N],vis2[N];
int ban[N][N];
void init()
{
f[0]=1;
for(int i=1;i<N;i++)
f[i]=(f[i-1]*i)%MOD;
}
void dfs(int k,int num)
{
if(k>m)
{
if(num&1) res=((res-f[n-num])%MOD+MOD)%MOD;
else res=(res+f[n-num])%MOD;
cout<<" res "<<res<<endl;
return ;
}
dfs(k+1,num);
if((!vis1[a[k][0]])&&(!vis2[a[k][1]]))
{
vis1[a[k][0]]=vis2[a[k][1]]=1;
dfs(k+1,num+1);
vis1[a[k][0]]=vis2[a[k][1]]=0;
}
}
int main()
{
init();
int i;
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;
}