题目

Description
【JZOJ 省选模拟】Permutation_题组

Input
【JZOJ 省选模拟】Permutation_题组_02

Output
一行一个数,表示答案。

Sample Input
输入样例1:
7 998244353
5 2 2
7 6 2
7 5 4
5 3 4
7 1 2
3 4 2

Sample Output
样例输出1:
2016

Data Constraint

【JZOJ 省选模拟】Permutation_题组_03

思路

真·签到题

对于每个点,容斥时合并颜色0以及所有连向儿子边的颜色的复杂度总和是O(n2)的
设u向父亲的颜色为f,显然开头结尾的颜色是f
考虑这样一种容斥:对于颜色f,要求它不能违反限制,对于剩下的颜色考虑它们违反了多少限制并容斥
首先对于其它的容斥,设f有a个,容斥后一种方案当前为b个数任意排列,那么最后一步的方案数为b!*C(a-2,b-1)

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std; 
const int N=5077; 
int n,mod; 
ll fac[2*N],unfac[2*N]; 
int ls[N],nx[N*2],to[N*2],cnt,w[N*2],sz[N]; 
void add(int x,int y,int v)
{
	to[++cnt] = y,nx[cnt] = ls[x],ls[x] = cnt; 
	w[cnt] = v; 
}

ll power(ll x,ll t)
{
	ll b=1;
	while(t)
	{
		if(t&1) b=b*x%mod;
		x=x*x%mod; t>>=1;
	}
	return b;
}

int fa[N],f[N][N],g[N]; 
void add(int &a,int b)
{
	a+=b; if(a>=mod)a-=mod;  else
	if(a<=-mod)a+=mod; 
}
ll C(ll n,ll m) 
{
	if(n<m)return 0; 
	return fac[n]*unfac[m]%mod*unfac[n-m]%mod; 
}
int yjy[N];
int tmp[N]; 
void solve(int x)
{
	sz[x]=1; f[x][1]=1; 
	
	for(int i=ls[x]; i; i=nx[i])
	{
		int y=to[i]; if(y==fa[x])continue; 
		int b=w[i]>>1; 
		fa[y]=x;  yjy[y]=b; 
		solve(y); 
		memset(tmp,0,sizeof tmp); 
		if(b>sz[y])
		{
			printf("0");  return;
		}
		for(int i=1; i<=b; i++) f[y][i]=g[y]*(((b-i)&1)==0?1:-1)*C(b,i)%mod; 
		for(int a=1; a<=sz[x]; a++)
		{
			for(int j=1; j<=b; j++){
				add(tmp[a+j],(ll)j*f[x][a]%mod*f[y][j]%mod*C(a+j-1,j)%mod); 
			}
		}
		memcpy(f[x],tmp,sizeof tmp); 
		sz[x]+=sz[y]; 
	}
	for(int a=yjy[x]; a<=sz[x]; a++)
	{
		add(g[x],f[x][a]*C(a,yjy[x])%mod); 
	}

}
int main()
{
//	freopen("permutation.in","r",stdin);  freopen("permutation.out","w",stdout); 
	scanf("%d%d",&n,&mod);
	for(int i = 1;  i < n;  i++)
	{
		int x,y,v;
		scanf("%d%d%d",&x,&y,&v); 
		add(x,y,v),add(y,x,v);  
		if(v&1)
		{
			printf("0");  return 0; 
		}
	}
	fac[0]=1; 
	for(int i=1; i<=2*n; i++) fac[i]=fac[i-1]*i%mod; 
	unfac[2*n]=power(fac[2*n],mod-2); 
	for(int i=2*n-1; ~i; i--) unfac[i]=unfac[i+1]*(i+1)%mod; 
	solve(1); 
	printf("%lld",(ll)n*((g[1]+mod)%mod)%mod); 
}