链接:https://ac.nowcoder.com/acm/contest/139/B
来源:牛客网
题目描述
Count the number of n x n matrices A satisfying the following condition modulo m.
* Ai, j ∈ {0, 1, 2} for all 1 ≤ i, j ≤ n.
* Ai, j = Aj, i for all 1 ≤ i, j ≤ n.
* Ai, 1 + Ai, 2 + ... + Ai, n = 2 for all 1 ≤ i ≤ n.
* A1, 1 = A2, 2 = ... = An, n = 0.
输入描述:
The input consists of several test cases and is terminated by end-of-file. Each test case contains two integers n and m.
输出描述:
For each test case, print an integer which denotes the result.
首先,要想到把矩阵化为图。这个矩阵满足邻接矩阵的性质,考虑每行和为2,即每个点的度为2.
考虑这个图的性质,一定是一些简单环。
假设我们已经求出点为n-1时的情况数,那么考虑加入一个点的情况数。加入一个点一定是要成一个新环的,我们要拿出一些点来与它成环,假设我们拿出了k个点,有C(n,k)种选法,k个点成k!种排列,加一个点成环,对于一个以上的点来说,因为是环所以要除以2.
所以 f (i) = f (i-2)*(i-1) +sigma c(n,n-k)*f(k)*(n-k)!/2
化简一下: f (i) = f (i-2)*(i-1) +sigma (n-1)!/k!*f(k)/2
但是这个式子复杂度显然不对,所以还要继续优化。
考虑 f(i-1) =f(i-3)*(i-2) +sigma(n-2)!/k!*f(k)/2
发现在求和部分如果我们将f(i-1)乘上(n-1),那么和f(i)就只差一项了。
所以 f(i)-f(i-1)*(i-1)=f(i-2)*(i-1)-f(i-3)*(i-2)*(i-1)+f(i-3)*(i-2)*(i-1)/2
即f(i)=f(i-1)*(i-1)+f(i-2)*(i-1)-f(i-3)*(i-1)*(i-2)/2
#include <bits/stdc++.h>
using namespace std;
#define go(i,a,b) for(int i=(a);i<=(b);i++)
#define ll long long
#define N 200005
int n,m;
ll f[N];
int main()
{
while(scanf("%d%d",&n,&m)!=EOF){
if(m==1){puts("0");continue; }
f[1]=0;f[2]=1;f[3]=1;
go(i,4,n)f[i]=(f[i-1]*(i-1)+f[i-2]*(i-1)-1ll*(i-2)*(i-1)/2%m*f[i-3]%m+m)%m;
printf("%lld\n",f[n]);
}
}