hard(2018.10.18)
题意:给你一棵\(n\)个节点的树,\(q\)个询问,每次询问读入\(u,v,k,op\),需要满足树上有\(k\)对点的简单路径交都等于\(u,v\)之间的简单路径,\(op=1\)表示\(k\)对点中每个点只能存在于一个点对中,否则每个点可以存在于多个点对中,问那k对点有多少种选法,答案对\(998244353\)取模。
数据范围:对于\(100%\)的数据,保证 \(1≤n≤10^5,1≤u,v≤n,u \ne v,1≤k≤min(n,500),op∈{0,1}\),保证每个节点的度数不超过\(500\)。
我们抓住“两两路径之交是\((u,v)\)”这条性质。 可以发现\(u,v\)是独立的。我们等价于要求:在\(u\)的子树中选\(k\)个点使它们两两\(lca\)是\(u\)的方案数,对\(v\)也求同样的东西,再把两者相乘。如果\(u,v\)存在祖孙关系,不妨设\(u\)是\(v\)的祖先,那么\(u\)的子树就要改为以\(v\)的方向作为根方向前提下的子树。 显然为了使两两\(lca\)是\(u\),在\(u\)的每一个儿子中就至多只能选一个点。然后这题就差不多了。
设\(g[x][i]\)为在\(x\)的子树里选\(i\)个点的方案数,\(ans\)为最后的答案,\(u,v\)为读入的\(u,v\),钦定\(u\)为深度小的那个点,\(tmp\)为\(u-v\)路径上最靠近\(u\)的那个点
那么有:
\]
\]
注意:\(k\)个点对是不等价的,比如说我们可以选\((i,j)\)为第一个点对和选\((i,j)\)为第二个点对是两种方案。
代码:
#include<cstdio>
#include<algorithm>
int n,q,cnt,fac[501],inv[501],facinv[501],pre[200001],nxt[200001],h[100001],f[100001][20],size[100001],dep[100001],mod=998244353;
struct oo{
int d[601],du;oo(){d[du=0]=1;}
void add(int x){du++;for(int i=du;i;i--)d[i]=(d[i]+1ll*d[i-1]*x)%mod;}
void del(int x){for(int i=1;i<=du;i++)d[i]=((d[i]-1ll*d[i-1]*x)%mod+mod)%mod;du--;}
int cal(int x,int op){int ans=0;for(int i=op?x-1:0;i<=x;i++)ans=(ans+1ll*d[i]*facinv[x-i])%mod;return (1ll*ans*fac[x])%mod;}
}g[100001];
void add(int x,int y){
pre[++cnt]=y;nxt[cnt]=h[x];h[x]=cnt;
pre[++cnt]=x;nxt[cnt]=h[y];h[y]=cnt;}
void dfs(int x){size[x]=1;
for(int i=1;i<20;i++){if(dep[x]<(1<<i))break;f[x][i]=f[f[x][i-1]][i-1];}
for(int i=h[x];i;i=nxt[i])if(pre[i]!=f[x][0]){dep[pre[i]]=dep[x]+1,f[pre[i]][0]=x,dfs(pre[i]),size[x]+=size[pre[i]];g[x].add(size[pre[i]]);}}
int lca(int x,int y){
if(dep[x]>dep[y])std::swap(x,y);int poor=dep[y]-dep[x];
for(int i=19;i>=0;i--)if(poor&(1<<i))y=f[y][i];
for(int i=19;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
if(x==y)return x;return f[x][0];}
int get(int x,int y){int poor=dep[x]-dep[y]-1;for(int i=19;i>=0;i--)if(poor&(1<<i))x=f[x][i];return x;}
int main(){
scanf("%d%d",&n,&q);inv[1]=fac[0]=facinv[0]=1;for(int i=2;i<=500;i++)inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod;
for(int i=1;i<=500;i++)fac[i]=1ll*fac[i-1]*i%mod,facinv[i]=1ll*facinv[i-1]*inv[i]%mod;
for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),add(x,y);dfs(1);
for(int i=1,u,v,k,op;i<=q;i++){
scanf("%d%d%d%d",&u,&v,&k,&op);if(dep[u]>dep[v])std::swap(u,v);
if(lca(u,v)==u){
int now=get(v,u);oo s=g[u];s.del(size[now]),s.add(n-size[u]);
printf("%d\n",(1ll*s.cal(k,op)*g[v].cal(k,op))%mod);}
else printf("%d\n",(1ll*g[u].cal(k,op)*g[v].cal(k,op))%mod);}}
hard(2018.10.18)的更多相关文章
- 2018.10.18 bzoj1185: [HNOI2007]最小矩形覆盖(旋转卡壳)
传送门 不难看出最后的矩形一定有一条边与凸包某条边重合. 因此先求出凸包,然后旋转卡壳求出当前最小矩形面积更新答案. 代码: #include<bits/stdc++.h> #define ...
- cdq(2018.10.18)
一句话题意:给你三个数列{a_i},{b_i},{c_i},保证每个数列都恰好是一个排列.你需要求出满足\(a_i<a_j,b_i<b_j,c_i<c_j\)的有序对\((i,j)\ ...
- 【2018.10.18】noip模拟赛Day2 地球危机(2018年第九届蓝桥杯C/C++A组省赛 三体攻击)
题目描述 三体人将对地球发起攻击.为了抵御攻击,地球人派出了 $A × B × C$ 艘战舰,在太 空中排成一个 $A$ 层 $B$ 行 $C$ 列的立方体.其中,第 $i$ 层第 $j$ 行第 $k ...
- 2018.10.18 NOIP训练 01矩阵(组合数学)
传送门 组合数学好题. 题目要求输出的结果成功把概率转化成了种类数. 本来可以枚举统计最小值为iii时的概率. 现在只需要统计最小值为iii时的方案数,每一行有不少于iii个1的方案数. 显然一行选i ...
- 2018.10.18 NOIP训练 [SCOI2018]Pipi 酱的日常(线段树)
传送门 线段树好题啊. 题目要求的是sum−a−b−c+maxsum-a-b-c+maxsum−a−b−c+max{∣a+v∣+∣b+v∣+∣c+v∣|a+v|+|b+v|+|c+v|∣a+v∣+∣b ...
- 2018.10.18 NOIP训练 ZUA球困难综合征(线段树)
传送门 考虑到模数等于7 * 13 * 17 * 19. 那么只需要维护四棵线段树求出每个数处理之后模7,13,17,197,13,17,197,13,17,19的值再用crtcrtcrt合并就行了. ...
- 2018.10.18 poj2187Beauty Contest(旋转卡壳)
传送门 旋转卡壳板子题. 就是求凸包上最远点对. 直接上双指针维护旋转卡壳就行了. 注意要时刻更新最大值. 代码: #include<iostream> #include<cstdi ...
- 2018.10.18 bzoj4105: [Thu Summer Camp 2015]平方运算(线段树)
传送门 线段树妙题. 显然平方几次就会循环(打表证明不解释). 然后所有环长度的lcmlcmlcm不大于70. 因此维护一下当前区间中的节点是否全部在环上. 不是直接暴力到叶子节点修改. 否则整体打标 ...
- 【2018.10.18】CXM笔记(动态规划)
1.给你一棵树,让你修任意多条点不相交的铁路(每条铁路都是一根链),定义一个点的代价为它到根节点的路径中不在铁路上的边数,求一种设计方案代价最大的点最小. 铁路点不相交与 每个点连出去的铁路条数 $\ ...
随机推荐
- mongodb学习之:条件操作符
在前面的章节中我们已经有用到了条件操作符,这里我们再重点介绍下.MongoDB中条件操作符有: (>) 大于 - $gt (<) 小于 - $lt (>=) 大于等于 - $gte ...
- 项目中一个普通的Java类如何获取serviceimpl实现类(二)
HbOnLineConfigServiceImpl hbOnlineService=(HbOnLineConfigServiceImpl) WebContextFactoryUtil.getBean( ...
- LVS集群的负载调度
LVS集群的负载调度 章文嵩 (wensong@linux-vs.org) 转自LVS官方资料 2002 年 5 月 本文主要讲述了LVS集群的IP负载均衡软件IPVS在内核中实现的各种连接调度算法. ...
- shared SDK 微信开放平台遇到的问题
shared sdk是用于集成到app中,方便快速社交化分享的组件,其使用方法比较简单,参考官网的快速集成步骤就能搞定.稍微麻烦一点的就是需要到各个开放平台去注册你的APP. 在各个开放平台注册好之后 ...
- 常用的ES6
1 let 和 const 作用域: 只在声明指令的块级作用域内有效.① let所声明的变量可以改变,值和类型都可以改变,没有限制. let a = 123 a = 456 // 正确,可以改变 le ...
- 脚踏实地学C#3-装箱和拆箱
装箱:一种接受值类型的值,根据这个值在堆中创建一个完整的引用类型对象并返回对象的引用(堆地址)的隐式转换 int i_number = 2; //在栈中声明int类型i_Number变量并初始化 ob ...
- [转]text和content方法的区别
r.text str #字符串方式的响应体,会自动根据响应头部的 字符编码进行解码 r.content bytes #字节方式的响应体,会自动为你解码 gzip 和 deflate 压缩 reques ...
- RequireJS 配置理解
RequireJS 配置: 1.首先加载RequireJS文件 <script src="//cdn.bootcss.com/require.js/2.1.22/require.js& ...
- 百度API从经纬度坐标到地址的转换服务
/// <summary> /// 百度API从经纬度坐标到地址的转换服务 /// </summary> /// <param name="lng"& ...
- darknet源码学习
darknet是一个较为轻型的完全基于C与CUDA的开源深度学习框架,其主要特点就是容易安装,没有任何依赖项(OpenCV都可以不用),移植性非常好,支持CPU与GPU两种计算方式.1.test源码( ...