首页 > 其他分享 >错落的时间拉不回疾驰而过的反向的平行线

错落的时间拉不回疾驰而过的反向的平行线

时间:2024-03-16 11:15:21浏览次数:12  
标签:平行线 frac int sum -- 错落 拉不回 myplus mod

T3

statement

有一个有权完全图,每次等概率选择一个点对 \((u,v)\),把这条边的权值 \(v=(v+1)\bmod 3\),\(q\) 次询问,求 \(t\) 次操作后的图的所有生成树的边权乘积的和的期望。

\(n\leq 50,q\leq 10^4,t\leq 10^{18}\)

solution

首先经典套路,把每条边看成一个二元多项式,求所有生成树的多项式乘积和 \(T\),那么 \([x^iy^j]T\) 就是 \(i\) 条 \(1\) 边,\(j\) 条 \(2\) 边的生成树个数,这个可以用二元拉格朗日插值求出来。

可以 \(dp\) 出来一个 \(f_{i,j}\)表示 假如最后有 \(i\) 条边被 \(+1\),\(j\) 条边被 \(+2\),\(n-1-i-j\) 条边被 \(+0\),剩下 \(\binom{n}{2}-n+1\) 条边无限制的所有生成树的权值和。

现在我们就要把 \(t\) 次操作分配给这些东西,考虑列出 \(EGF\) ,并使用单位根反演,设 \(3\) 次单位根为 \(w\)。

假设我们要求出

\[\begin{align} F_k(x) & = \sum\limits_{i=0}[i\bmod 3=k]\frac{x^i}{i!} \\ & = \sum\limits_{i=0}[3|(i-k)]\frac{x^i}{i!} \\ & = \frac{1}{3}\sum\limits_{i=0}\sum\limits_{j=0}^2w^{j(i-k)}\frac{x^i}{i!} \\ & = \frac{1}{3}\sum\limits_{j=0}^2w^{-jk}\sum\limits_{i=0}\frac{(w^j x)^i}{i!} \\ & = \frac{1}{3}\sum\limits_{j=0}^2w^{-jk}e^{w^j x} \\ \end{align} \]

  • 边权不变

    \[F_0=\frac{1}{3} (e ^ {w^2 x} + e ^ {w x} + e ^x) \]

  • 边权加一

    \[F_1=\frac{1}{3}(w^2 e^{wx}+we^{w^2x}+e^x) \]

  • 边权加二

    \[F_2=\frac{1}{3}(we^{wx}+w^2e^{w^2x}+e^x) \]

那么我们要求

\[[x^t]F_0^{n-1-i-j}F_1^{i}F_2^{j}(e^x)^{\binom{n}{2}-n+1} \]

因为 \(w^2=-w-1\),所以上述 \(EGF\) 一定能表示成 \(\sum_{a,b}[x^t]e^{(aw+b)x}g_{a,b}\) 的形式,\((a,b)\) 只有 \(O(n^2)\) 个,所以可以 \(O(n^2\log t)\) 计算,可以用光速幂去掉 $\log $,总复杂度 \(O(n^5+qn^2)\)。

code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 55;
const int mod = 1e9+9;
const int i3=(mod*2+1)/3;
inline void myplus(int &x,int y){x+=y;if(x>=mod) x-=mod;}
inline void reduce(int &x,int y){x-=y;if(x<0) x+=mod;}
LL Pow(LL a,LL b)
{
	LL res=1;
	while(b)
	{
		if(b&1)res=res*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return res;
}
inline LL Inv(LL x){return Pow(x,mod-2);}
const LL w=Pow(13,(mod-1)/3),w2=w*w%mod;
int n,m,q;
int e[N][N];
int inv[N],fac[N],ifac[N];
void pre()
{
	inv[1]=fac[1]=fac[0]=ifac[0]=ifac[1]=1;
	for(int i=2;i<=n;i++)
	{
		inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod;
		fac[i]=1ll*fac[i-1]*i%mod;
		ifac[i]=1ll*ifac[i-1]*inv[i]%mod;
	}
}
int p[N][N];
namespace det
{
	int d[N][N];
	int f[N][N];
	int det(int x)
	{
		int res=1;
		for(int i=1;i<=x;i++)
		{
			if(!d[i][i])
			{
				int id=i;
				for(int j=i+1;j<=x;j++) if(d[j][i]) id=j;
				swap(d[id],d[i]);res=-res;
			}
			LL inv=Inv(d[i][i]);
			for(int j=i+1;j<=x;j++)
			{
				int t=1ll*d[j][i]*inv%mod;
				for(int k=i;k<=x;k++) reduce(d[j][k],1ll*d[i][k]*t%mod);
			}
		}
		res+=mod;
		for(int i=1;i<=x;i++) res=1ll*res*d[i][i]%mod;
		return res;
	}
	int B[N][N];
	int F[N],G[N];
	void init()
	{
		F[0]=1;
		for(int i=1;i<=n;i++)
		{
			for(int j=i;j>=0;j--)
			{
				F[j]=1ll*F[j]*(mod-i)%mod;
				if(j) myplus(F[j],F[j-1]);
			}
		}
	}
	void preinit(int x)
	{
		for(int i=1;i<=n;i++)
		{
			int w=f[x][i];
			for(int j=1;j<=n;j++) if(j!=i) w=1ll*w*(i<j?mod-inv[j-i]:inv[i-j])%mod;
			for(int j=n-1;j>=0;j--) G[j]=(F[j+1]+1ll*G[j+1]*i)%mod;
			for(int j=0;j<n;j++) myplus(B[x][j],1ll*w*G[j]%mod);
		}
	}
	void lagrange()
	{
		for(int i=1;i<=n;i++)
		{
			int w=1;
			for(int j=1;j<=n;j++) if(j!=i) w=1ll*w*(i<j?mod-inv[j-i]:inv[i-j])%mod;
			for(int j=n-1;j>=0;j--) G[j]=(F[j+1]+1ll*G[j+1]*i)%mod;
			for(int j=0;j<n;j++) for(int k=0;k<n;k++)myplus(p[j][k],1ll*B[i][k]*G[j]%mod*w%mod);
		} 
	}
	void pre()
	{
		for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		{
			memset(d,0,sizeof(d));
			for(int u=1;u<=n;u++) 
			for(int v=u+1;v<=n;v++)
			{
				int val=(e[u][v]==0?1:(e[u][v]==1?i:j));
				myplus(d[u][u],val);myplus(d[v][v],val);
				reduce(d[u][v],val);reduce(d[v][u],val);
			}
			f[i][j]=det(n-1);
		}
		init();
		for(int i=1;i<=n;i++) preinit(i);
		lagrange(); 
	}
}
int f[N][N];
namespace F
{
	int g[N][N];
	void pre()
	{
		for(int i=0;i<n;i++) 
		for(int j=0;j<n;j++) 
		if(p[i][j])
		{
			memset(g,0,sizeof(g));
			g[0][0]=p[i][j];
			for(int k=1;k<=i;k++)for(int l=n-1;l>=0;l--)
			if(l) myplus(g[l][0],1ll*g[l-1][0]*2%mod);
			for(int k=1;k<=j;k++)for(int l=n-1;l>=0;l--)for(int o=n-1-l;o>=0;o--)
			{
				myplus(g[l][o],g[l][o]);
				if(o) myplus(g[l][o],g[l][o-1]);
			}
			for(int k=1;k<=n-1-i-j;k++)for(int l=n-1;l>=0;l--)for(int o=n-1-l;o>=0;o--)
			{
				g[l][o]=0;
				if(l) myplus(g[l][o],g[l-1][o]);
				if(o) myplus(g[l][o],1ll*g[l][o-1]*2%mod);
			}
			for(int k=0;k<n;k++)for(int l=0;l+k<n;l++)myplus(f[k][l],g[k][l]);
		}
	}
}
int g[N*2][N*2];
namespace G
{
	int f[N*2][N*2],tf[N*2][N*2];
	void s1()
	{
		memset(tf,0,sizeof(tf));
		for(int i=1;i<2*n;i++) for(int j=1;j<2*n;j++) if(f[i][j])
		{
			myplus(tf[i][j+1],w2*f[i][j]%mod);
			myplus(tf[i-1][j-1],w*f[i][j]%mod);
			myplus(tf[i+1][j],f[i][j]);
		}
		memcpy(f,tf,sizeof(f));
	}
	void s2()
	{
		memset(tf,0,sizeof(tf));
		for(int i=1;i<2*n;i++) for(int j=1;j<2*n;j++) if(f[i][j])
		{
			myplus(tf[i][j+1],w*f[i][j]%mod);
			myplus(tf[i-1][j-1],w2*f[i][j]%mod);
			myplus(tf[i+1][j],f[i][j]);
		}
		memcpy(f,tf,sizeof(f));
	}
	void s0()
	{
		memset(tf,0,sizeof(tf));
		for(int i=1;i<2*n;i++) for(int j=1;j<2*n;j++) if(f[i][j])
		{
			myplus(tf[i][j+1],f[i][j]);myplus(tf[i-1][j-1],f[i][j]);myplus(tf[i+1][j],f[i][j]);
		}
		memcpy(f,tf,sizeof(f));
	}
	void pre()
	{
		LL pw=Pow(i3,n-1);
		for(int i=0;i<n;i++)for(int j=0;j<n;j++) if(::f[i][j])
		{
			memset(f,0,sizeof(f));
			f[n][n]=pw*::f[i][j]%mod;
			for(int k=1;k<=n-1-i-j;k++) s0();
			for(int k=1;k<=i;k++) s1();
			for(int k=1;k<=j;k++) s2();
			for(int k=1;k<2*n;k++) for(int l=1;l<2*n;l++) myplus(g[k][l],f[k][l]);
		}
	}
}
int main()
{
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	cin>>n>>m>>q;
	for(int i=1;i<=m;i++)
	{
		int u,v,w;cin>>u>>v>>w;
		e[u][v]=e[v][u]=w;
	}
	pre();det::pre();F::pre();G::pre();
	int C=(n-2)*(n-1)/2;
	while(q--)
	{
		LL t;
		scanf("%lld",&t);
		t%=mod-1;
		int ans=0;
		for(int i=1;i<2*n;i++)for(int j=1;j<2*n;j++)if(g[i][j])
		{
			int v=((i-n+mod+C)%mod+1ll*(j-n+mod)*w%mod)%mod;
			myplus(ans,1ll*g[i][j]*Pow(v,t)%mod);
		}
		ans=1ll*ans*Inv(Pow(n*(n-1)/2,t))%mod;
		printf("%d\n",ans);
	}
	return 0;
}
/*
3 2 3
1 2 1
2 3 2
0
1
2

*/

标签:平行线,frac,int,sum,--,错落,拉不回,myplus,mod
From: https://www.cnblogs.com/jesoyizexry/p/18076804

相关文章