当$k$个集合依次为$S_{1},S_{2},...,S_{k}$时,称$x$合法当且仅当:
1.$forall 1le ile k,xin S_{i}$
2.$forall yin igcup_{i=1}^{k}S_{i}$,$dis(x,y) imes v_{y}le Max$
注意到这些合法的$x$必然构成一个连通块,证明如下:
考虑两个合法点$x$和$y$以及$x$到$y$这条路径上一个点$z$($z e x,y$),由于$S_{i}$要求连通,因此$zin S_{i}$,同时对于任意点$t$,$dis(z,t) imes v_{t}<max(dis(x,t),dis(y,t)) imes v_{t}le Max$,因此也满足第2个条件
此时,我们就可以利用点数-边数=1的性质,具体来说:
对于所有$x$,求出令$x$合法的方案数;对于所有$(x,y)$,求出令$(x,y)$合法的方案数(称一条边$(x,y)in E$合法当且仅当$x$合法且$y$合法)
将两者相减,考虑使得合法集合非空的方案,该合法集合中每一个点都贡献了1个收益,每一条边都贡献了一个-1的收益,因此一共恰好被计算点数-边数=1次
令$x$合法的方案数,可以通过dp求,具体来说,由于强制包含$x$,以$x$为根建树后在dfs序上dp,状态中关于价值的一维强制最大,即再记录另一个dp数组表示最大价值即可
(特别的,要对无$dis(x,y) imes v_{y}$的限制再做一次,因为对于“完美的集合”没有这个限制,若这样的最大值更大则答案必然为0)
接下来,我们相当于要计算一个组合数,可以转换为阶乘的形式,即求$n!equiv ans(mod 5^{23})$(题中所给的大模数即为$5^{23}$,另外注意乘法需要转换为加法,可以以500为进制)
$o(log_{5}n)$统计出其中5的次数,用$5^{t}v$的形式来表示(其中$5 otmid v$)答案,之后记$g_{n}=prod_{1le ile n,5 otmid i}i$,即有$v=prod_{ige 0}g_{lfloorfrac{n}{5^{i}} floor}$,接下来即考虑如何求$g_{n}$(这个$n$代指$lfloorfrac{n}{5^{i}} floor$)
记$n'=lfloorfrac{n}{5} floor$,则有$g_{n}=g_{5n'}prod_{i=5n'+1}^{n}i$,后者暴力计算即可,之后即求$g_{5n'}$
构造函数$f_{n}(x)=prod_{1le ile 5n,5 otmid i}(x+i)$(用多项式的形式存储),初始$f_{0}(x)=1$,即求$g_{5n'}=f_{n'}(x)[x^{0}]$(指常数项系数)
考虑$f_{2n}(x)=f_{n}(x)f_{n}(x+5n)$和$f_{n+1}=f_{n}(x)prod_{i=1}^{4}(x+5n+i)$,由此即可推出$f_{n'}(x)$,但如果暴力计算,复杂度为$o(n^{2}log_{2}n)$
事实上,对于$f_{n}(x)[x^{i}]$,我们只关心于其对$5^{23-i}$取模的结果,那么对$ige 23$时即对1取模,显然不需要计算,因此仅保留前23项(具体实现都对$5^{23}$取模即可),复杂度降为$o(23^{2}log_{2}n)$
由于乘法还需要一个log,以及要计算$o(log_{5}n)$个$g_{n}$,总复杂度为$o(n^{2}m+23^{2}nlog^{3}mod)$,可以通过
关于$f_{n}(x)[x^{i}]$对$5^{23-i}$取模的证明:
归纳这样的正确性,称$f(x)=f'(x)$当且仅当$f(x)[x^{i}]equiv f'(x)[x^{i}](mod 5^{23-i})$
接下来即求证若$f_{n}(x)=f'_{n}(x)$,$f_{2n}(x)=f'_{2n}(x)$且$f_{n+1}(x)=f'_{n+1}(x)$
先考虑对于$f(x)=f'(x)$且$g(x)=g'(x)$,不难推得$f(x)g(x)=f'(x)g'(x)$,那么对于$f_{n+1}(x)=f'_{n+1}(x)$正确性显然
同时对于$f_{2n}(x)=f'_{2n}(x)$,也就是要证明$f_{n}(x+5n)=f'_{n}(x+5n)$,代入后也可以证明
根据上面的这个性质,不难得到最终$f_{n}(x)=f'_{n}(x)$,即$f'_{n'}[x^{0}]equiv f_{n'}[x^{0}](mod 5^{23})$
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 105 4 #define M 10005 5 #define ll long long 6 #define pll pair<ll,ll> 7 #define fi first 8 #define se second 9 struct ji{ 10 int nex,to,len; 11 }edge[N<<1]; 12 pll g[M],f[N][M]; 13 int E,n,m,k,x,y,z,head[N],w[N],v[N],dfn[N],sz[N],dep[N]; 14 ll lim,mod,mx,ans; 15 void add(int x,int y,int z){ 16 edge[E].nex=head[x]; 17 edge[E].to=y; 18 edge[E].len=z; 19 head[x]=E++; 20 } 21 void dfs(int k,int fa,int s){ 22 dfn[++dfn[0]]=k; 23 sz[k]=1; 24 dep[k]=s; 25 for(int i=head[k];i!=-1;i=edge[i].nex) 26 if (edge[i].to!=fa){ 27 dfs(edge[i].to,k,s+edge[i].len); 28 sz[k]+=sz[edge[i].to]; 29 } 30 } 31 ll mul(ll x,ll y){ 32 ll s=x,ans=0; 33 while (y){ 34 ans=(ans+y%500*s)%mod; 35 s=500*s%mod; 36 y/=500; 37 } 38 return ans; 39 } 40 void exgcd(ll a,ll b,ll &x,ll &y){ 41 if (!b){ 42 x=1,y=0; 43 return; 44 } 45 exgcd(b,a%b,y,x); 46 y-=(a/b)*x; 47 } 48 struct num{ 49 ll t,v; 50 num operator * (const num &k)const{ 51 return num{t+k.t,mul(v,k.v)}; 52 } 53 num inv(){ 54 ll x,y; 55 exgcd(v,mod,x,y); 56 if (x>=0)x%=mod; 57 else x+=(-x+mod-1)/mod*mod; 58 return num{-t,x}; 59 } 60 }o; 61 struct poly{ 62 ll a[23]; 63 poly(int k){ 64 memset(a,0,sizeof(a)); 65 a[0]=k; 66 } 67 poly operator + (const poly &k)const{ 68 poly ans=poly(0); 69 for(int i=0;i<23;i++)ans.a[i]=(a[i]+k.a[i])%mod; 70 return ans; 71 } 72 poly operator * (const poly &k)const{ 73 poly ans=poly(0); 74 for(int i=0;i<23;i++) 75 for(int j=0;j<23;j++) 76 if (i+j<23)ans.a[i+j]=(ans.a[i+j]+mul(a[i],k.a[j]))%mod; 77 return ans; 78 } 79 }; 80 poly dfs(ll n){ 81 poly ans=poly(1); 82 if (!n)return ans; 83 ans=dfs(n>>1); 84 poly s=poly(1),ss=poly(0); 85 for(int i=0;i<23;i++){ 86 for(int j=0;j<=i;j++)ss.a[j]=(ss.a[j]+mul(s.a[j],ans.a[i]))%mod; 87 for(int j=min(i+1,22);j;j--)s.a[j]=(mul(s.a[j],5*(n/2))+s.a[j-1])%mod; 88 s.a[0]=mul(s.a[0],5*(n/2)); 89 } 90 ans=ans*ss; 91 if (n&1) 92 for(int i=1;i<5;i++){ 93 for(int j=22;j;j--)ans.a[j]=(mul(ans.a[j],5*(n-1)+i)+ans.a[j-1])%mod; 94 ans.a[0]=mul(ans.a[0],5*(n-1)+i); 95 } 96 return ans; 97 } 98 ll fac_5(ll n){ 99 ll nn=n/5,ans=1; 100 for(ll i=nn*5+1;i<=n;i++)ans=mul(ans,i); 101 return mul(ans,dfs(nn).a[0]); 102 } 103 num fac(ll n){ 104 num ans=num{0,fac_5(n)}; 105 for(ll i=5;i<=n;i*=5){ 106 ans.t+=n/i; 107 ans.v=mul(ans.v,fac_5(n/i)); 108 } 109 return ans; 110 } 111 ll c(ll n,ll m){ 112 if (n<m)return 0; 113 num ans=fac(n)*o*fac(n-m).inv(); 114 if (ans.t>=23)return 0; 115 for(int i=0;i<ans.t;i++)ans.v=ans.v*5%mod; 116 return ans.v; 117 } 118 pll merge(pll x,pll y){ 119 if (x.fi<y.fi){ 120 x.fi=y.fi; 121 x.se=0; 122 } 123 if (x.fi==y.fi)x.se=(x.se+y.se)%mod; 124 return x; 125 } 126 void calc(int p){ 127 f[dfn[0]+1][0]=make_pair(0,1); 128 for(int i=1;i<=m;i++)f[dfn[0]+1][i]=make_pair(-1,0); 129 for(int i=dfn[0];i;i--){ 130 int x=dfn[i]; 131 for(int j=0;j<=m;j++)f[i][j]=f[i+sz[x]][j]; 132 if ((p)&&(1LL*dep[x]*v[x]>lim))continue; 133 for(int j=m;j>=w[x];j--){ 134 pll o=f[i+1][j-w[x]]; 135 o.fi+=v[x]; 136 f[i][j]=merge(f[i][j],o); 137 } 138 } 139 } 140 int main(){ 141 mod=1; 142 for(int i=0;i<23;i++)mod*=5; 143 scanf("%d%d%d%lld",&n,&m,&k,&lim); 144 o=fac(k).inv(); 145 for(int i=1;i<=n;i++)scanf("%d",&w[i]); 146 for(int i=1;i<=n;i++)scanf("%d",&v[i]); 147 memset(head,-1,sizeof(head)); 148 for(int i=1;i<n;i++){ 149 scanf("%d%d%d",&x,&y,&z); 150 add(x,y,z); 151 add(y,x,z); 152 } 153 for(int i=1;i<=n;i++){ 154 dfn[0]=0; 155 dfs(i,0,0); 156 calc(0); 157 for(int j=0;j<=m;j++)mx=max(mx,f[1][j].fi); 158 } 159 for(int i=1;i<=n;i++){ 160 dfn[0]=0; 161 dfs(i,0,0); 162 calc(1); 163 ll sum=0; 164 for(int j=0;j<=m;j++) 165 if (f[1][j].fi==mx)sum=(sum+f[1][j].se)%mod; 166 ans=(ans+c(sum,k))%mod; 167 } 168 for(int i=0;i<E;i+=2){ 169 int x=edge[i].to,y=edge[i^1].to; 170 dfn[0]=0; 171 dfs(x,y,edge[i].len); 172 calc(1); 173 g[0]=make_pair(-1,0); 174 for(int j=1;j<=m;j++)g[j]=merge(g[j-1],f[1][j]); 175 dfn[0]=0; 176 dfs(y,x,edge[i].len); 177 calc(1); 178 ll sum=0; 179 for(int j=w[x];j<=m-w[y];j++) 180 if (g[j].fi+f[1][m-j].fi==mx)sum=(sum+mul(g[j].se,f[1][m-j].se))%mod; 181 ans=(ans+mod-c(sum,k))%mod; 182 } 183 printf("%lld",ans); 184 }