题目
Description
Input
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
思路
真·签到题
对于每个点,容斥时合并颜色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);
}