Symmetric Matrix

题意:

问有多少个矩阵A满足如下性质


* 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.

思路:即问给定一张图,每个点的度都是2(都是环),问有少种构图方案

f(n):n个点时,有多少种构图方案,使得所有点的度都为2

f(n)可以从f(n-1)推导过来。假设我从n-1里   取出k个和新来的第n个  组成环,那么新环的方式有 (k+1)!/(2*(k+1)) , 因为对于每2(k+1)个环中,只有1个环是有用的。因为k+1条边,随便断一条边,对应的全排列是重复的,顺着和逆着再乘上个2.但是发现对于k=1的情况不用除,那么把k=1独立出来,剩下k∈[2,n-1]写个sigma 。写出公式就是下面这样

#include<bits/stdc++.h>
#define PI acos(-1.0)
#define pb push_back
#define F first
#define S second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e5+5;
//const int MOD=1e9+7;
template <class T>
bool sf(T &ret){ //Faster Input
 
    char c; int sgn; T bit=0.1;
    if(c=getchar(),c==EOF) return 0;
    while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();
    sgn=(c=='-')?-1:1;
    ret=(c=='-')?0:(c-'0');
    while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
    if(c==' '||c=='\n'){ ret*=sgn; return 1; }
    while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;
    ret*=sgn;
    return 1;
}
ll ans[N];
ll n,m;
 
int main(void){
    while((scanf("%lld%lld",&n,&m))==2){
        ans[1]=0;
        ans[2]=ans[3]=1ll;
        for(ll i=4;i<=n;i++){
            ans[i]=ans[i-1]*(i-1)%m+ans[i-2]*(i-1)%m-(i-1)*(i-2)/2*ans[i-3]%m;
            ans[i]=(ans[i]%m+m)%m;
        }
        printf("%lld\n",ans[n]);
    }
    return 0;
}