当$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. 消息队列那么多,为什么建议深入了解下RabbitMQ?

    你为啥要在项目中选择xxx消息中间件? 提起消息队列,也许你的脑海里会不自觉地蹦出好多概念:JMS.Kafka.RocketMQ.AMQP.RabbitMQ.ActiveMQ.Pulsar.Redis ...

  2. pandas 取 groupby 后每个分组的前 N 行

    原始数据如下: (图是从 excel 截的,最左1行不是数据,是 excel 自带的行号,为了方便说明截进来的) 除去首行是标题外,有效数据为 28行 x 4列 目前的需求是根据 partition ...

  3. 每日一题,是否存在(c语言)

    每日一题:1.是否存在 是否存在描述猫咪非常喜欢饼干,尤其是字母饼干.现在,她得到一些字母饼干,她希望选择他们中的一些拼写某些单词. 你的任务是确定她是否可以拼出自己想要的单词. 输入输入包含若干测试 ...

  4. 【数据结构与算法Python版学习笔记】图——词梯问题 广度优先搜索 BFS

    词梯Word Ladder问题 要求是相邻两个单词之间差异只能是1个字母,如FOOL变SAGE: FOOL >> POOL >> POLL >> POLE > ...

  5. vue3.x新特性之setup函数,看完就会用了

    最近有小伙伴跟我聊起setup函数,因为习惯了vue2.x的写法导致了,setup用起来觉得奇奇怪怪的,在一些api混编的情况下,代码变得更加混乱了,个人觉得在工程化思想比较强的团队中使用setup确 ...

  6. 痞子衡嵌入式:超级下载算法RT-UFL v1.0在Keil MDK下的使用

    痞子衡主导的"学术"项目 <RT-UFL - 一个适用全平台i.MXRT的超级下载算法设计> v1.0 版发布近 4 个月了,部分客户已经在实际项目开发调试中用上了这个 ...

  7. Request failed with status code 500以及自引用循环Self referencing loop detected for property ‘xx‘ with type

    错误Error: Request failed with status code 500 ,调试前端没问题,后端也没问题,还报错"连接超时" 在Network中找到错误Self r ...

  8. Linux过来人帮你理清学习思路

    很多同学接触linux不多,对linux平台的开发更是一无所知. 而现在的趋势越来越表明,作为一个优秀的软件开发人员,或计算机it行业从业人员,="" 掌握linux是一种很重要的 ...

  9. ES查询区分大小写

    ES查询区分大小写 ES查询在默认的情况下是不区分大小写的,在5.0版本之后将string类型拆分成两种新的数据类型,text用于全文搜索(模糊搜索),keyword用于关键字搜索(精确搜索). 注意 ...

  10. Verdi Protocol Analyzer Debug 简单使用

    转载:Verdi Protocol Analyzer Debug 简单使用_Holden_Liu的博客-CSDN博客_verdi 技巧 文档与源码: User Guide: UVMDebugUserG ...