Codeforces997D Cycles in product 【FFT】【树形DP】
题目大意:
给两个树,求环的个数。
题目分析:
出题人摆错题号系列。
通过画图很容易就能想到把新图拆在两个树上,在树上游走成环。
考虑DP状态F,G,T。F表示最终答案,T表示儿子不考虑父亲,G表示父亲不考虑儿子。T通过从下往上做NTT,G通过从上往下做NTT。F顺便做NTT。
最后做一下拼接就行。
代码:
#include<bits/stdc++.h>
using namespace std; const int maxn = ;
const int mod = ;
const int gg = ; int n[],k; vector <int> g[][maxn]; int f[][maxn][],gi[][maxn][],T[][maxn][]; int C[][]; int fast_pow(int now,int pw){
int ans = ,bit = ,dt = now;
while(bit <= pw){
if(bit & pw){ans = (1ll*ans*dt)%mod;}
bit <<=; dt = (1ll*dt*dt)%mod;
}
return ans;
} void read(){
scanf("%d%d%d",&n[],&n[],&k);
for(int i=;i<n[];i++){
int u,v; scanf("%d%d",&u,&v);
g[][u].push_back(v); g[][v].push_back(u);
}
for(int i=;i<n[];i++){
int u,v; scanf("%d%d",&u,&v);
g[][u].push_back(v); g[][v].push_back(u);
}
} int ord[]; void NTT(int *d,int len,int dr){
for(int i=;i<len;i++) if(ord[i] < i) swap(d[i],d[ord[i]]);
for(int i=;i<len;i<<=){
int wn = fast_pow(gg,(mod-)/(*i));
if(dr == -) wn = fast_pow(wn,mod-);
for(int j=;j<len;j+=(i<<)){
for(int k=,w=;k<i;k++,w = (1ll*w*wn)%mod){
int x = d[j+k],y = (1ll*w*d[j+k+i])%mod;
d[j+k] = (x+y)%mod;
d[j+k+i] = (x-y+mod)%mod;
}
}
}
if(dr == -){
int iv = fast_pow(len,mod-);
for(int i=;i<len;i++) d[i] = (1ll*d[i]*iv)%mod;
}
} int A[],B[];
int fi[],A0[]; void INV(){
int len = ,bit = ; while(len <= k) len<<=,bit++;
memset(A0,,sizeof(A0));memset(fi,,sizeof(fi));
A0[] = ;
for(int i=,j=;i<=len;i<<=,j++){
for(int k=;k<i;k++) fi[k] = A[k];
int rl = i*,rb = j+;
for(int k=;k<rl;k++) ord[k] = (ord[k>>]>>) + ((k&)<<rb-);
NTT(A0,rl,); NTT(fi,rl,);
for(int k=;k<rl;k++){
A0[k] = (*A0[k]-(1ll*fi[k]*A0[k]%mod)*A0[k]%mod)%mod;
if(A0[k] < ) A0[k] += mod;
}
NTT(A0,rl,-);
for(int k=i;k<rl;k++) A0[k] = fi[k] = ;
}
for(int i=;i<=k;i++) A[i] = A0[i];
} void dfs1(int kd,int now,int fa){
for(auto it:g[kd][now]){
if(it == fa) continue;
dfs1(kd,it,now);
}
memset(A,,sizeof(A));
for(auto it:g[kd][now]){
if(it == fa) continue;
for(int i=;i<=k-;i+=) A[i+] = (A[i+]+T[kd][it][i])%mod;
}
A[] -= ; if(A[] < ) A[] += mod;
for(int i=;i<=k;i++){ A[i] *= -; if(A[i] < ) A[i] += mod;}
INV();
for(int i=;i<=k;i++) T[kd][now][i] = A[i];
} void dfs2(int kd,int now,int fa){
memset(B,,sizeof(B));
for(auto it:g[kd][now]){
if(it == fa) continue;
for(int i=;i<=k-;i+=) B[i+] = (B[i+]+T[kd][it][i])%mod;
}
for(int i=;i<=k-;i+=) B[i+] = (B[i+]+gi[kd][now][i])%mod;
for(auto it:g[kd][now]){
if(it == fa) continue;
for(int i=;i<=k-;i+=) B[i+] = (B[i+]+mod-T[kd][it][i])%mod;
memset(A,,sizeof(A));
for(int i=;i<=k;i++) A[i] = (mod-B[i])%mod; A[] = (-A[]+mod)%mod;
INV(); for(int i=;i<=k;i++) gi[kd][it][i] = A[i];
for(int i=;i<=k-;i+=) B[i+] = (B[i+]+T[kd][it][i])%mod;
}
memset(A,,sizeof(A));
for(int i=;i<=k;i++) A[i] = (mod-B[i])%mod; A[] = (-A[]+mod)%mod;
INV(); for(int i=;i<=k;i++) f[kd][now][i] = A[i];
for(auto it:g[kd][now]){
if(it == fa) continue;
dfs2(kd,it,now);
}
} void solve(int kd){
dfs1(kd,,);
dfs2(kd,,);
} void work(){
solve();
solve();
for(int i=;i<=k;i++){
C[i][] = C[i][i] = ;
for(int j=;j<i;j++) C[i][j] = (C[i-][j] + C[i-][j-]) % mod;
}
int ans = ;
for(int i=;i<=k;i++){
int s1 = ,s2 = ;
for(int j=;j<=n[];j++) s1 += f[][j][i],s1 %= mod;
for(int j=;j<=n[];j++) s2 += f[][j][k-i],s2 %= mod;
int pp = (1ll*s1*s2)%mod;pp = (1ll*C[k][i]*pp)%mod;
ans += pp; ans %= mod;
}
printf("%d",ans);
} int main(){
read();
work();
return ;
}
Codeforces997D Cycles in product 【FFT】【树形DP】的更多相关文章
- 树形DP 2013多校8(Terrorist’s destroy HDU4679)
题意: There is a city which is built like a tree.A terrorist wants to destroy the city's roads. But no ...
- codeforces 161D Distance in Tree 树形dp
题目链接: http://codeforces.com/contest/161/problem/D D. Distance in Tree time limit per test 3 secondsm ...
- poj2378 树形DP
C - 树形dp Crawling in process... Crawling failed Time Limit:1000MS Memory Limit:65536KB 64bit ...
- 秘密袭击 [BZOJ5250] [树形DP]
分析: 听说正解是FFT+线段树合并,然而我并不会... 我们来思考其他的方法. 我们要求的是连通块第k大的和 对于某一个连通块,对答案的贡献=val(Rank.K) 我们不好直接算出每个连通块的Ra ...
- Codeforces Beta Round #14 (Div. 2) D. Two Paths 树形dp
D. Two Paths 题目连接: http://codeforces.com/contest/14/problem/D Description As you know, Bob's brother ...
- Codeforces Beta Round #14 (Div. 2) Two Paths (树形DP)
Two Paths time limit per test 2 seconds memory limit per test 64 megabytes input standard input outp ...
- 树的直径的求法即相关证明【树形DP || DFS】
学习大佬:树的直径求法及证明 树的直径 定义: 一棵树的直径就是这棵树上存在的最长路径. 给定一棵树,树中每条边都有一个权值,树中两点之间的距离定义为连接两点的路径边权之和.树中最远的两个节点之间的距 ...
- 5.21 省选模拟赛 luogu P4297 [NOI2006]网络收费 树形dp
LINK:网络收费 还是自己没脑子. 早上思考的时候 发现树形dp不可做 然后放弃治疗了. 没有合理的转换问题的模型是我整个人最大的败笔. 暴力也值得一提 爆搜之后可以写成FFT的形式的计算贡献的方法 ...
- poj3417 LCA + 树形dp
Network Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4478 Accepted: 1292 Descripti ...
随机推荐
- Python-SMTP发送邮件(HTML、图片、附件)
前言: SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式. 一.Python发送HTML ...
- E. Superhero Battle
链接 [https://codeforces.com/contest/1141/problem/E] 题意 怪物开始的生命值,然后第i分钟生命值的变化 问什么时候怪物生命值为非正 分析 有一个巨大的坑 ...
- 2018软工实践K班总结
再回首一学期的软工实践,首先还是要感谢两位助教童鞋帮我承担了作业发布.打分以及与学生的问题沟通等.从这次的软工实践80人+开始,之后的实践课变为必修,故如何能更有效地组织大班实践环节是一个需要持续探讨 ...
- case when then的用法-leetcode交换工资
case具有两种格式:简单case函数和case搜索函数. --简单case函数 case sex when ' then '男' when ' then '女’ else '其他' end --ca ...
- 软工网络15团队作业7——Alpha冲刺之事后诸葛亮
Deadline: 2018-5-16 22:00PM,以博客提交至班级博客时间为准 事后诸葛亮分析 Alpha冲刺,很多同学经历了"Learning by doing"的学一门新 ...
- 搭建RISC-V错误记录
错误:riscv64-unknown-elf-gcc: Command not found 解决办法:将riscv64-unknown-elf-gcc文件拷贝到根目录的/bin目录下. 原因是make ...
- Windows10下安装VMware虚拟机并搭建CentOS系统环境
转载: http://blog.51cto.com/10085711/2069270 操作系统 Windows 10专业版(64位) VMware虚拟机 产品:VMware® Workstation ...
- MySQL的SQL语句优化-group by语句的优化
原文:http://bbs.landingbj.com/t-0-243202-1.html 默认情况下,MySQL排序所有GROUP BY col1, col2, ....,查询的方法如同在查询中指定 ...
- Oracle NVL空值处理函数
--NVL空值处理函数 --需求:显示价格表中业主类型ID为1的价格记录 如果上限值为null,则显示9999999 ) from dual; select * from t_pricetable ) ...
- jQuery 事件 - triggerHandler() 方法
定义和用法 triggerHandler() 方法触发被选元素的指定事件类型.但不会执行浏览器默认动作,也不会产生事件冒泡. triggerHandler() 方法与 trigger() 方法类似.不 ...