[loj2462]完美的集合
不难证明,能作为测试装置的$x$构成一个连通块(或为空)
在此基础上,利用非空连通块点数-边数=1进行统计,具体即——
假设有$f_{x}$个$S$能以$x$作为测试装置$,g_{(x,y)}$个$S$能同时以$x$和$y$作为测试装置,则答案为
$$
\sum_{x\in V}{f_{x}\choose k}-\sum_{(x,y)\in E}{g_{(x,y)}\choose k}
$$
关于$f_{x}$和$g_{(x,y)}$,可以通过在dfs序上背包计算,单次背包复杂度为$o(nm)$
关于求${n\choose m}\ mod\ p^{k}$的问题,有如下方式——
将组合数转换为阶乘相除的形式,并以$p^{t}v(p\not\mid v)$的形式表示结果,即可支持除法
记$n_{0}=\lfloor\frac{n}{p}\rfloor$,则
$$
n!= \left(\prod_{1\le i\le n,p\mid i}i \right)\left(\prod_{1\le i\le n,p\not\mid i}i\right)=p^{n_{0}}n_{0}!\left(\prod_{1\le i\le n,p\not\mid i}i\right)
$$
关于$n_{0}!$可以递归处理,下面仅需求出最后一项——
记$\begin{cases}g(n,x)=\prod_{1\le i\le n,p\not\mid i}(x+i)\\f_{c}(x)=g(p^{c},x)\end{cases}$,则原式即$f_{k}(0)^{\lfloor\frac{n}{p^{k}}\rfloor}g(n\ mod\ p^{k},0)$
当$n<p^{k}$时,假设$n\in [p^{c},p^{c+1})$,取$n_{0}=\lfloor\frac{n}{p^{c}}\rfloor$,则转移即
$$
g(n,x)=\left(\prod_{i=0}^{n_{0}-1}f_{c}(x+i\cdot p^{c})\right)\cdot g(n-n_{0}\cdot p^{c},x+n_{0}\cdot p^{c})
$$
显然递归后$n<p^{c}$,因此至多递归$o(k)$层,第$c$层需对$f_{c}(x)$做$o(p)$次单点求值
注意到所求的点$x$均满足$p^{c}\mid x$,进而次数$\ge \lceil\frac{k}{c}\rceil$的项均无意义,仅需求出出前$\lceil\frac{k}{c}\rceil$项即可
关于预处理,转移即$f_{c}(x)=\prod_{i=0}^{p-1}f_{c-1}(x+i\cdot p^{c-1})$,保留$\lceil\frac{k}{c}\rceil$项并暴力展开&乘法即可
关于复杂度,注意到$\int_{1}^{\infty}\frac{1}{x^{2}}{\rm d}x=o(1)$,进而即$o(pk^{2})-o(pk\log k\log n)$
最终,总复杂度为$o(n^{2}m+n^{2}\log mod\log\log mod)$(这里认为组合数与$2^{n}$同级),可以通过
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100 4 #define M 10005 5 #define L 30 6 #define ll long long 7 #define LL __int128 8 #define pll pair<ll,ll> 9 #define fi first 10 #define se second 11 int n,m,W,E,x,y,z,w[N],v[N],head[N],dfn[N],idfn[N],sz[N]; 12 ll lim,mxv,sum,ans;pll g[M],f[M],dp[N][M]; 13 struct List{ 14 int nex,to,len; 15 }edge[N<<1]; 16 void add(int x,int y,int z){ 17 edge[E]=List{head[x],y,z}; 18 head[x]=E++; 19 } 20 void dfs(int k,int fa,int s,int p){ 21 if ((p)&&((ll)s*v[k]>lim)){ 22 sz[k]=0; 23 return; 24 } 25 dfn[k]=++dfn[0],idfn[dfn[0]]=k,sz[k]=1; 26 for(int i=head[k];i!=-1;i=edge[i].nex) 27 if (edge[i].to!=fa){ 28 dfs(edge[i].to,k,s+edge[i].len,p); 29 sz[k]+=sz[edge[i].to]; 30 } 31 } 32 pll add(pll x,int y){ 33 return make_pair(x.fi+y,x.se); 34 } 35 pll merge(pll x,pll y){ 36 pll ans=max(x,y); 37 if (x.fi==y.fi)ans.se=x.se+y.se; 38 return ans; 39 } 40 void calc(){ 41 memset(dp,0,sizeof(dp)); 42 int k=idfn[1]; 43 if (w[k]<=W)dp[1][w[k]]=make_pair(v[k],1); 44 for(int i=2;i<=dfn[0];i++){ 45 int k=idfn[i]; 46 for(int j=0;j<=W;j++) 47 if (dp[i-1][j].se){ 48 if (j+w[k]<=W)dp[i][j+w[k]]=merge(dp[i][j+w[k]],add(dp[i-1][j],v[k])); 49 dp[i+sz[k]-1][j]=merge(dp[i+sz[k]-1][j],dp[i-1][j]); 50 } 51 } 52 memcpy(f,dp[dfn[0]],sizeof(f)); 53 } 54 namespace Lucas{ 55 int P,K;ll mod,phi,pw[L],Pw[L],C[L][L]; 56 unordered_map<ll,ll>mat; 57 ll qpow(ll n,ll m){ 58 LL s=n,ans=1; 59 while (m){ 60 if (m&1)ans=ans*s%mod; 61 s=s*s%mod,m>>=1; 62 } 63 return ans; 64 } 65 struct Poly{ 66 ll a[L]; 67 Poly(){ 68 memset(a,0,sizeof(a)); 69 } 70 ll get(int n,ll x){ 71 ll s=1,ans=0; 72 for(int i=0;i<n;i++)ans=(ans+(LL)a[i]*s)%mod,s=(LL)s*x%mod; 73 return ans; 74 } 75 }f[L]; 76 Poly get_nex(Poly &a,int n,ll x){ 77 Pw[0]=1; 78 for(int i=1;i<n;i++)Pw[i]=(LL)Pw[i-1]*x%mod; 79 Poly ans; 80 for(int i=0;i<n;i++) 81 for(int j=0;j<=i;j++)ans.a[j]=(ans.a[j]+(LL)C[i][j]*Pw[i-j]%mod*a.a[i])%mod; 82 return ans; 83 } 84 Poly mul(Poly &a,Poly b,int n){ 85 Poly ans; 86 for(int i=0;i<n;i++) 87 for(int j=0;j<=i;j++)ans.a[i]=(ans.a[i]+(LL)a.a[i-j]*b.a[j])%mod; 88 return ans; 89 } 90 void build(int p,int k){ 91 P=p,K=k,pw[0]=1; 92 for(int i=1;i<=K;i++)pw[i]=pw[i-1]*P; 93 mod=pw[K],phi=(P-1)*pw[K-1],mat.clear(); 94 for(int i=0;i<K;i++){ 95 C[i][0]=C[i][i]=1; 96 for(int j=1;j<i;j++)C[i][j]=C[i-1][j-1]+C[i-1][j]; 97 } 98 Poly s;f[1]=Poly(),s.a[1]=f[1].a[0]=1; 99 for(int i=1;i<P;i++)s.a[0]=i,f[1]=mul(f[1],s,K); 100 for(int i=2;i<=K;i++){ 101 f[i]=Poly(),f[i].a[0]=1; 102 for(int j=0;j<P;j++)f[i]=mul(f[i],get_nex(f[i-1],(K+i-2)/(i-1),j*pw[i-1]),(K+i-1)/i); 103 } 104 } 105 ll get_fac_P(ll n){ 106 if (mat.find(n)!=mat.end())return mat[n]; 107 ll n0=n,x=0,ans=qpow(f[K].get(1,0),n/mod); 108 n%=mod; 109 for(int i=K-1;i;i--){ 110 int m=n/pw[i]; 111 for(int j=0;j<m;j++){ 112 ans=(LL)ans*f[i].get((K+i-1)/i,x)%mod; 113 n-=pw[i],x+=pw[i]; 114 } 115 } 116 for(int i=1;i<=n;i++)ans=(LL)ans*(x+i)%mod; 117 return mat[n0]=ans; 118 } 119 pll get_fac(ll n){ 120 ll n0=n; 121 pll ans=make_pair(0,1); 122 while (n)ans.fi+=n/P,ans.se=(LL)ans.se*get_fac_P(n)%mod,n/=P; 123 return ans; 124 } 125 ll calc(ll n,ll m){ 126 if (n<m)return 0; 127 pll s,ans=get_fac(n); 128 s=get_fac(m),ans.fi-=s.fi,ans.se=(LL)ans.se*qpow(s.se,phi-1)%mod; 129 s=get_fac(n-m),ans.fi-=s.fi,ans.se=(LL)ans.se*qpow(s.se,phi-1)%mod; 130 return (LL)ans.se*qpow(P,ans.fi)%mod; 131 } 132 }; 133 int main(){ 134 Lucas::build(5,23); 135 scanf("%d%d%d%lld",&n,&W,&m,&lim); 136 for(int i=1;i<=n;i++)scanf("%d",&w[i]); 137 for(int i=1;i<=n;i++)scanf("%d",&v[i]); 138 memset(head,-1,sizeof(head)); 139 for(int i=1;i<n;i++){ 140 scanf("%d%d%d",&x,&y,&z); 141 add(x,y,z),add(y,x,z); 142 } 143 for(int i=1;i<=n;i++){ 144 dfn[0]=0,dfs(i,0,0,0),calc(); 145 for(int j=0;j<=W;j++)mxv=max(mxv,f[j].fi); 146 } 147 for(int i=1;i<=n;i++){ 148 dfn[0]=sum=0,dfs(i,0,0,1),calc(); 149 for(int j=0;j<=W;j++) 150 if (f[j].fi==mxv)sum+=f[j].se; 151 ans=(ans+Lucas::calc(sum,m))%Lucas::mod; 152 } 153 for(int i=1;i<=n;i++) 154 for(int j=head[i];j!=-1;j=edge[j].nex) 155 if (i<edge[j].to){ 156 x=i,y=edge[j].to,z=edge[j].len; 157 dfn[0]=0,dfs(x,y,z,1),calc(),g[0]=f[0]; 158 for(int k=1;k<=W;k++)g[k]=merge(f[k],g[k-1]); 159 dfn[0]=sum=0,dfs(y,x,z,1),calc(); 160 for(int k=0;k<=W;k++) 161 if (f[k].fi+g[W-k].fi==mxv)sum+=f[k].se*g[W-k].se; 162 ans=(ans-Lucas::calc(sum,m)+Lucas::mod)%Lucas::mod; 163 } 164 printf("%lld\n",ans); 165 return 0; 166 }