当$k$个集合依次为$S_{1},S_{2},...,S_{k}$时,称$x$合法当且仅当:

1.$\forall 1\le i\le k,x\in S_{i}$

2.$\forall y\in \bigcup_{i=1}^{k}S_{i}$,$dis(x,y)\times v_{y}\le Max$

注意到这些合法的$x$必然构成一个连通块,证明如下:

考虑两个合法点$x$和$y$以及$x$到$y$这条路径上一个点$z$($z\ne x,y$),由于$S_{i}$要求连通,因此$z\in S_{i}$,同时对于任意点$t$,$dis(z,t)\times v_{t}<\max(dis(x,t),dis(y,t))\times 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)\times v_{y}$的限制再做一次,因为对于“完美的集合”没有这个限制,若这样的最大值更大则答案必然为0)

接下来,我们相当于要计算一个组合数,可以转换为阶乘的形式,即求$n!\equiv ans(mod\ 5^{23})$(题中所给的大模数即为$5^{23}$,另外注意乘法需要转换为加法,可以以500为进制)

$o(\log_{5}n)$统计出其中5的次数,用$5^{t}v$的形式来表示(其中$5\not\mid v$)答案,之后记$g_{n}=\prod_{1\le i\le n,5\not\mid i}i$,即有$v=\prod_{i\ge 0}g_{\lfloor\frac{n}{5^{i}}\rfloor}$,接下来即考虑如何求$g_{n}$(这个$n$代指$\lfloor\frac{n}{5^{i}}\rfloor$)

记$n'=\lfloor\frac{n}{5}\rfloor$,则有$g_{n}=g_{5n'}\prod_{i=5n'+1}^{n}i$,后者暴力计算即可,之后即求$g_{5n'}$

构造函数$f_{n}(x)=\prod_{1\le i\le 5n,5\not\mid 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}$取模的结果,那么对$i\ge 23$时即对1取模,显然不需要计算,因此仅保留前23项(具体实现都对$5^{23}$取模即可),复杂度降为$o(23^{2}\log_{2}n)$

由于乘法还需要一个log,以及要计算$o(\log_{5}n)$个$g_{n}$,总复杂度为$o(n^{2}m+23^{2}n\log^{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 }

[loj2462]完美的集合的更多相关文章

  1. 【题解】LOJ2462完美的集合(树DP 魔改Lucas)

    [题解]LOJ2462完美的集合(树DP 魔改Lucas) 省选模拟考这个??????????????????? 题目大意: 有一棵树,每个点有两个属性,一个是重量\(w_i\)一个是价值\(v_i\ ...

  2. extentreports报告插件之extentX之服务搭建(三)

    之前两个章节已经写完再extentreports报告插件与testng 的集成,但是发现 每次测试完后,生成的报告都要在单独发送,每个项目都有一份报告,如果项目多的话,管理起来就会很冗余. 这个给大家 ...

  3. java多线程:java队列详解

    队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作.进行插入操作的端称为队尾,进行删除操作的端称为队头.队列中没有元素时,称为空队列. 在队列这 ...

  4. Play中JSON序列化

    总的来说在scala体系下,对于习惯了java和c#这些常规开发的人来说,无论是akka-http还是play,就处理个json序列化与反序列化真他娘够费劲的. 根据经验,Json处理是比较简单的,但 ...

  5. Codeforces 388 D. Fox and Perfect Sets

    $ >Codeforces \space 388 D.  Fox and Perfect Sets<$ 题目大意 : 定义一个完美的集合 \(S\) ,当且仅当 \(S\) 非负非空,且 ...

  6. 自动化测试报告浅谈之ExtentReports

    我们在进行自动化测试时,往往需要有相应的测试报告,比如junit,testng,reportng等等,有会有自带的测试报告,那为什么我要在这边提ExtentReports?首先,我们来看看其它几种测试 ...

  7. 世界名校网络课程大盘点,美国大学CS专业十三大研究方向,世界50所知名大学提供开放课程

    世界名校网络课程大盘点   加州大学伯克利分校http://webcast.berkeley.edu/ 加州大学伯克利分校与斯坦福大学. 麻省理工学院等一同被誉为美国工程科技界的学术 领袖,其常年位居 ...

  8. POI完美解析Excel数据到对象集合中(可用于将EXCEL数据导入到数据库)

    实现思路: 1.获取WorkBook对象,在这里使用WorkbookFactory.create(is); // 这种方式解析Excel.2003/2007/2010都没问题: 2.对行数据进行解析 ...

  9. HTML5 oninput实时监听输入框值变化的完美方案

    在网页开发中经常会碰到需要动态监听输入框值变化的情况,如果使用 onkeydown.onkeypress.onkeyup 这个几个键盘事件来监测的话,监听不了右键的复制.剪贴和粘贴这些操作,处理组合快 ...

随机推荐

  1. 高级爬虫面试题测试题 v1.3

    Python Web高级爬虫工程师测试题 (请本文件发送到: SpiderTestQuestion@163.com 并附带简历) 1. 用yield写一个斐波那契数列的生成器函数. 2. 放一段scr ...

  2. bzoj4712 洪水(动态dp)

    看起来很模板的一个题啊 qwq 但是我还是wei 题目要求的是一个把根节点和所有叶子断开连接的最小花费. 还是想一个比较\(naive\)的做法 我们令\(dp1[i]\)表示,在\(i\)的子树内, ...

  3. bzoj1834 ZJOI2010网络扩容(费用流)

    给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用. 求: 1.在不扩容的情况下,1到N的最大流: 2.将1到N的最大流增加K所需的最小扩容费用. 其中\(n ...

  4. 【转载】[经验] 嵌入式stm32实用的排序算法 - 交换排序

    Ⅰ.写在前面 前面写了关于ADC采集电压的文章,大家除了求平均的方式来处理采样值,还有没有使用到其他的方式来处理采集值呢? 在某些情况下就需要对一组数据进行排序,并提取头特定的数据出来使用. 排序的应 ...

  5. CentOS 用户与群组

    目录 1.用户管理 1.1.切换用户 1.2.添加用户 1.3.删除用户 1.4.修改用户 2.群组管理 2.1.查看群组 2.2.添加群组 2.3.删除群组 2.4.修改群组 1.用户管理 Linu ...

  6. 【数据结构与算法Python版学习笔记】树——树的遍历 Tree Traversals

    遍历方式 前序遍历 在前序遍历中,先访问根节点,然后递归地前序遍历左子树,最后递归地前序遍历右子树. 中序遍历 在中序遍历中,先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树. 后序遍 ...

  7. 微信小程序的支付流程

    一.前言 微信小程序为电商类小程序,提供了非常完善.优秀.安全的支付功能 在小程序内可调用微信的API完成支付功能,方便.快捷 场景如下图所示: 用户通过分享或扫描二维码进入商户小程序,用户选择购买, ...

  8. Noip模拟71 2021.10.7

    T1 签到题 结论题,找到规律就会做 规律是每个点的度数$\mod$颜色种数,如果不是$0$则贡献一个答案 1 #include<bits/stdc++.h> 2 #define int ...

  9. DMA实现采样数据的直接搬运存储

    尝试了下STM32的ADC采样,并利用DMA实现采样数据的直接搬运存储,这样就不用CPU去参与操作了. 找了不少例子参考,ADC和DMA的设置了解了个大概,并直接利用开发板来做一些实验来验证相关的操作 ...

  10. 『学了就忘』Linux基础 — 15、了解Linux系统的目录结构

    目录 1.一级目录说明 (1)一级目录列表 (2)/bin/和/sbin/目录说明 (3)/boot/目录说明 (4)/lib/和/lib64/目录说明 (5)/lost+found/目录说明 (6) ...