当$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. JVM学习笔记——GC垃圾收集器

    GC 垃圾收集器 Java 堆内存采用分代回收算法,因此 JVM 针对新生代和老年代提供了多种垃圾收集器. 1. Serial 收集器 Serial 收集器是单线程收集器,采用复制算法. 是最基本的垃 ...

  2. Netty 了解

    1.1 Netty 是什么? Netty is an asynchronous event-driven network application framework for rapid develop ...

  3. 8086的复位与启动 CPU执行指令的步骤

    东北大学-计算机硬件技术基础 CPU执行指令的步骤 取指令 Fetch 指令译码 Decode 执行指令 Execute 回写 Write-back 修改指令指针 取指令 将CS和IP的内容通过地址加 ...

  4. Java(14)面向对象之封装

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201610.html 博客主页:https://www.cnblogs.com/testero ...

  5. ScatterLayout分散布局在kv中的引用

    from kivy.uix.scatterlayout import ScatterLayout from kivy.app import App class ScatterLayoutWidget( ...

  6. [no code][scrum meeting] Alpha 15

    项目 内容 会议时间 2020-04-23 会议主题 OCR紧急会议 会议时长 45min 参会人员 PM + OCR组(赵涛,黎正宇) 项目 内容 会议时间 2020-04-24 会议主题 全体测试 ...

  7. [BZOI2014]大融合——————线段树进阶

    竟然改了不到一小时就改出来了, 可喜可贺 Description Solution 一开始想的是边两侧简单路径之和的乘积,之后发现这是个树形结构,简单路径数就是节点数. 之后的难点就变成了如何求线段树 ...

  8. [luogu2973]driving out the piggies 驱逐猪猡【高斯消元+概率DP】

    看到题面的那一刻,我是绝望的ORZ 图论加概率期望加好像不沾边的高斯消元???我人直接傻掉 还没学过概率期望的我果断向题解屈服了(然后还是傻掉了两节课来找线性方程.. Description 奶牛们建 ...

  9. 零基础入门之Linux进程基础

    计算机实际上可以做的事情实质上非常简单,比如计算两个数的和,再比如在内存中寻找到某个地址等等.这些最基础的计算机动作被称为指令(instruction).所谓的程序(program),就是这样一系列指 ...

  10. accept error: Too many open files

    今天测试socket服务器同一时间处理多个客户端连接问题,第一次测试1000个的时候没问题,第二次测试1000个服务器accept的时候就报错了 accept error: Too many open ...