[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}$同级),可以通过

  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 }
View Code

 

posted @ 2021-01-25 14:09  PYWBKTDA  阅读(230)  评论(0编辑  收藏  举报