天天看點

JZOJ 3059. 【NOIP2012模拟10.26】雕塑分析:代碼:

...

  • 分析:
  • 代碼:

分析:

總方案數顯然是 n ! n! n!

但是題目中有障礙物,是以我們考慮用總方案數-障礙物的方案數

但随後我們發現,答案貌似不太對!——因為我們計算了重複的部分。是以我們就使用容斥原了解決

代碼:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#include<deque>
#include<set>
#define LL long long
using namespace std;
inline LL read(){
	LL d=0,f=1;char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
	while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
	return d*f;
}
int n,m,q,r[50],a[50][5],h[50],s[50];
LL d[50],ans;
void dfs(int o,int t){
	if(!t){
		r[q]++;return;
	}
	for(int i=o+1;i<=m;++i)
	if(!h[a[i][1]]&&!s[a[i][2]])
	{
		h[a[i][1]]=1;s[a[i][2]]=1;
		dfs(i,t-1);
		h[a[i][1]]=0;s[a[i][2]]=0;
	}
}
int main()
{
	n=read();m=read();
	for(int i=1;i<=m;++i) a[i][1]=read(),a[i][2]=read();
	for(q=1;q<=m;++q) dfs(0,q);
	d[1]=1;d[0]=1;
	for(int i=2;i<=n;++i) d[i]=d[i-1]*i;
	ans=1;
	for(int i=2;i<=n;++i) ans*=i;
	for(int i=1;i<=m;++i)
	  if(i%2==1) ans-=r[i]*d[n-i];
	  else ans+=r[i]*d[n-i];
	cout<<ans;
	return 0;
}
           

繼續閱讀