【JZOJ B組】小A做CF
阿新 • • 發佈:2018-12-13
Description
目標rating超過CLJ的小A最近在瘋狂做CF,話說這次CF在賽前十分鐘出了個相當奇葩的預選題,要求十分鐘內必須做出這道題才能參加這次CF。 這道題是這樣的,給你一個N*N的矩陣,每行有一個障礙,資料保證任意兩個障礙不在同一行,任意兩個障礙不在同一列,要求你在這個矩陣上放N枚棋子(障礙的位置不能放棋子),要求你放N個棋子也滿足每行只有一枚棋子,每列只有一枚棋子的限制,求有多少種方案。 最近被各種神題折磨得死去活來,走火入魔的小A一下被這個超級水題給卡住了,但是這次是超過CLJ的最佳機會,於是,心急火燎的他找到了你,請你帶他順利參加這次CF正賽吧。
Input
第一行一個N,接下來一個N*N的矩陣。
Output
合法方案數。
Sample Input
2 0 1 1 0
Sample Output
1
Data Constraint
20%的資料保證: N<=10 60%的資料保證: N<=20 100%的資料保證: N<=200
思路
本題目由於障礙其實是順序無關的(從每行每列不重複可看出),於是可以將棋盤進行轉化
然後可以通過求空白棋盤和有障礙棋盤的方案數,再相乘可得。如果將列位置看成數列的位置,行位置看做數列中的數,顯然可以看出棋盤擺棋情況可對映為一個數列,於是有:空白棋盤方案:(全排列)n!帶障礙棋盤方案:用錯排公式(就是由 n 個人坐座位,然後進行換位,每個人不能坐在原位置的方案數),遞推式:f[i]=(i-1)*(f[i-1]+f[i-2])
ps:正解要高精度
程式碼
#include<iostream>
#include<cstdio>
using namespace std;
int n;
long long f[500];
int main()
{
scanf("%d",&n);
f[1]=0; f[2]=1;
for(int i=3; i<=n; i++) f[i]=1ll*(i-1)*(f[i-1]+f[i-2]);
printf("%lld",f[n]);
}