题意:给你一棵\(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\)的那个点

那么有:

\[if(lca(u,v)==u)ans=tmp[k]*g[v][k]
\]

\[else\ \ \ \ \ \ \ ans=g[u][k]*g[v][k]
\]

注意:\(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)的更多相关文章

  1. 2018.10.18 bzoj1185: [HNOI2007]最小矩形覆盖(旋转卡壳)

    传送门 不难看出最后的矩形一定有一条边与凸包某条边重合. 因此先求出凸包,然后旋转卡壳求出当前最小矩形面积更新答案. 代码: #include<bits/stdc++.h> #define ...

  2. cdq(2018.10.18)

    一句话题意:给你三个数列{a_i},{b_i},{c_i},保证每个数列都恰好是一个排列.你需要求出满足\(a_i<a_j,b_i<b_j,c_i<c_j\)的有序对\((i,j)\ ...

  3. 【2018.10.18】noip模拟赛Day2 地球危机(2018年第九届蓝桥杯C/C++A组省赛 三体攻击)

    题目描述 三体人将对地球发起攻击.为了抵御攻击,地球人派出了 $A × B × C$ 艘战舰,在太 空中排成一个 $A$ 层 $B$ 行 $C$ 列的立方体.其中,第 $i$ 层第 $j$ 行第 $k ...

  4. 2018.10.18 NOIP训练 01矩阵(组合数学)

    传送门 组合数学好题. 题目要求输出的结果成功把概率转化成了种类数. 本来可以枚举统计最小值为iii时的概率. 现在只需要统计最小值为iii时的方案数,每一行有不少于iii个1的方案数. 显然一行选i ...

  5. 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 ...

  6. 2018.10.18 NOIP训练 ZUA球困难综合征(线段树)

    传送门 考虑到模数等于7 * 13 * 17 * 19. 那么只需要维护四棵线段树求出每个数处理之后模7,13,17,197,13,17,197,13,17,19的值再用crtcrtcrt合并就行了. ...

  7. 2018.10.18 poj2187Beauty Contest(旋转卡壳)

    传送门 旋转卡壳板子题. 就是求凸包上最远点对. 直接上双指针维护旋转卡壳就行了. 注意要时刻更新最大值. 代码: #include<iostream> #include<cstdi ...

  8. 2018.10.18 bzoj4105: [Thu Summer Camp 2015]平方运算(线段树)

    传送门 线段树妙题. 显然平方几次就会循环(打表证明不解释). 然后所有环长度的lcmlcmlcm不大于70. 因此维护一下当前区间中的节点是否全部在环上. 不是直接暴力到叶子节点修改. 否则整体打标 ...

  9. 【2018.10.18】CXM笔记(动态规划)

    1.给你一棵树,让你修任意多条点不相交的铁路(每条铁路都是一根链),定义一个点的代价为它到根节点的路径中不在铁路上的边数,求一种设计方案代价最大的点最小. 铁路点不相交与 每个点连出去的铁路条数 $\ ...

随机推荐

  1. java之选择排序

     //选择排序(Select Sorting)也是一种简单的排序方法.它的基本思想是:第一次从R[0]-R[n-1]中选取最小值,与R[0]交换,第二次从R[1]-R[n-1]中选取最小值,与R[1] ...

  2. Ubuntu Firefox没有声音的解决方案

    安装ubuntu-restricted-extras sudo apt-get install ubuntu-restricted-extras 参考博文:解决ubuntu中firefox没有声音的问 ...

  3. 把tomcat写到Windows系统服务器的服务中

    首先准备一个免安装的tomcat服务器,和一个Windows系统. 在“C:\Windows\SysWOW64”中找到cmd.exe的执行文件,以管理员身份启动: 进入到tomcat的bin文件夹, ...

  4. JVM client模式和Server模式

    我们把jdk安装完成后,在命名行输入java -version 不仅可以看到jdk版本相关信息,还会看到类似与 Java HotSpot(TM) 64-Bit Server VM (build 25. ...

  5. CSU - 1530 Gold Rush —— 二进制

    题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1530 对于一块2^n质量的gold.需要把它分成a质量和b质量(a+b=2^n),且 ...

  6. [原创]Java开发如何在线打开Word文件

    此方案使用了PageOffice产品实现在线打开Word文档: 1. 首先从PageOffice官网下载产品开发包,http://www.zhuozhengsoft.com/dowm/ ,下载Page ...

  7. webrtc 学习资源

    http://www.cnblogs.com/lingyunhu/tag/webrtc%20android%20ios/

  8. C/C++的const区别

    1.const基础知识(用法.含义.好处) int main() { const int a; //a为const,常数型数 int const b; //b为const,常数型数 const int ...

  9. Linux终端程序用c语言实现改变输出的字的颜色

    颜色代码: 格式: echo "\033[字背景颜色;字体颜色m字符串\033[0m" 例如: echo "\033[41;36m something here \033 ...

  10. Thread之二:sleep、wait、yield、join

    一.回顾下概念 Java中的多线程是一种抢占式的机制而不是分时机制.线程主要有以下几种状态:新建,就绪,运行,阻塞,死亡.抢占式机制指的是有多个线程处于就绪状态,但是只有一个线程在运行.   1.sl ...