参考一下题解,我们先将已经固定的棋子查找出来,并且计数,从而求出我们需要放的自由棋子的数量,这样我们就我们不必考虑黑白棋子的位置,我们只考虑我们可以自由摆放的棋子的个数,每当增加新的一行和一列的时候我们能需要考虑两种情况
1.我们可以在新的增加的一行一列中的中剪,也就是i,i 位置添加一种棋子,这是dp[i-1]
2.也可以在i,j位置添加一种棋子,这样需要占用两行两列,并且有i-1种位置可以添加,并且是黑白2种棋子,这是2*(i-1)*dp[i-2]
#include<iostream> #include<algorithm> #include<cstring> using namespace std ; const int N = 3e5+10 ,M = 1e9 + 7 ; int dp[N] ; int t , n , q ; int main(){ cin >> t ; while(t --){ memset(dp,0,sizeof(dp)) ;//每一次进行清零 cin >> n >> q ; int ans = 0 ; while(q --){ int x , y ; cin >> x >> y ; ans += (2 - (x==y)) ;//记录我们已经用过的行和列 } dp[0] = 1 ; //初始化,当没有空余的行和列的时候我们只能等于本来的已经固定的棋子方案书 //dp[1] = 1 ; //当只有一行一列的时候我们只能添加 i,i 这种方式 int m = n - ans ; for(int i = 2 ; i <= m ; i++){ dp[i] =(dp[i-1] % M + ((long long)2*(i-1)*dp[i-2]) % M) %M ; } cout << dp[m] << endl ; } return 0 ; }