Petit_Souris
2024-11-17 13:22:23
验题人题解,大概做了 1.5h 不到过了。
首先这个
把贡献拆开,枚举两条链,计算这两条链同色的方案数。假设他们重合了
考虑容斥(二项式反演)。计算
如何计算
这个做法的时间复杂度为
考虑优化。首先这个转移同时枚举
还能再给力点吗?发现我们最后其实并不关心每个
正确的打开方式是考虑二项式反演中
稍微卡卡常数就不大了。
#include<bits/stdc++.h>
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define pii pair<ll,ll>
#define rep(i,a,b) for(ll i=(a);i<=(b);++i)
#define per(i,a,b) for(ll i=(a);i>=(b);--i)
using namespace std;
bool Mbe;
ll read(){
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void write(ll x){
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
}
const ll N=309,Mod=998244353;
ll typ,n,k,L,M;
ll f[N][N][22],ed[N][22],st[N][22],g[N][22][22],h[N][22][22],C[22][22];
ll ord[N],deg[N];
vector<pii>to[N];
ll pw(ll x,ll p){
ll res=1;
while(p){
if(p&1)res=res*x%Mod;
x=x*x%Mod,p>>=1;
}
return res;
}
bool Med;
int main(){
freopen("party.in","r",stdin);
freopen("party.out","w",stdout);
cerr<<fabs(&Med-&Mbe)/1048576.0<<"MB\n";
typ=read(),n=read(),k=read(),L=read(),M=read();
rep(i,1,M){
ll x=read(),y=read(),z=read();
to[x].push_back({y,z}),deg[y]++;
}
rep(i,0,L){
C[i][0]=1;
rep(j,1,i)C[i][j]=(C[i-1][j]+C[i-1][j-1])%Mod;
}
queue<ll>q;
rep(i,1,n){
if(!deg[i])q.push(i);
}
while(!q.empty()){
ll u=q.front();q.pop();
ord[++ord[0]]=u;
for(pii e:to[u]){
ll v=e.first;
deg[v]--;
if(!deg[v])q.push(v);
}
}
ord[0]=0;
rep(i,1,n){
ll u=ord[i];
f[u][u][1]=1;
rep(j,i,n){
ll v=ord[j];
rep(k,1,L-1){
if(!f[u][v][k])continue;
for(pii e:to[v]){
ll w=e.first,ww=e.second;
f[u][w][k+1]=(f[u][w][k+1]+f[u][v][k]*ww)%Mod;
}
}
}
}
rep(i,1,n){
rep(j,1,n){
rep(k,1,L){
st[i][k]=(st[i][k]+f[i][j][k])%Mod;
ed[j][k]=(ed[j][k]+f[i][j][k])%Mod;
}
}
}
cerr<<"\n"<<clock()*1.0/CLOCKS_PER_SEC*1000<<"ms\n";
ll ans=0;
rep(i,1,n){
rep(j,1,n)ans=(ans+f[i][j][L])%Mod;
}
ans=ans*ans%Mod;
rep(i,1,n){
ll u=ord[i];
rep(l1,1,L){
rep(l2,1,L)g[u][l1][l2]=(g[u][l1][l2]+ed[u][l1]*ed[u][l2]%Mod*(k-1))%Mod;
}
memset(h,0,sizeof(h));
rep(j,i+1,n){
ll v=ord[j];
rep(l1,1,L){
rep(l2,1,L){
if(!g[u][l1][l2])continue;
rep(t1,1,L-l1){
if(!f[u][v][t1+1])continue;
h[v][l1+t1][l2]=(h[v][l1+t1][l2]+g[u][l1][l2]*f[u][v][t1+1])%Mod;
}
}
}
}
rep(j,i+1,n){
ll v=ord[j];
rep(l1,1,L){
rep(l2,1,L){
if(!h[v][l1][l2])continue;
rep(t2,1,L-l2){
if(!f[u][v][t2+1])continue;
g[v][l1][l2+t2]=(g[v][l1][l2+t2]+h[v][l1][l2]*f[u][v][t2+1]%Mod*(k-1))%Mod;
}
}
}
}
}
rep(i,1,n){
ll u=ord[i];
rep(l1,1,L){
rep(l2,1,L){
if(!g[u][l1][l2])continue;
ans=(ans+g[u][l1][l2]*st[u][L-l1+1]%Mod*st[u][L-l2+1])%Mod;
}
}
}
if(n-2*L+1<0)ans=ans*pw(pw(k,Mod-2),-(n-2*L+1))%Mod;
else ans=ans*pw(k,n-2*L+1)%Mod;
write(ans),putchar('\n');
cerr<<"\n"<<clock()*1.0/CLOCKS_PER_SEC*1000<<"ms\n";
return 0;
}