题目大意:

给两个树,求环的个数。

题目分析:

出题人摆错题号系列。

通过画图很容易就能想到把新图拆在两个树上,在树上游走成环。

考虑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】的更多相关文章

  1. 树形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 ...

  2. codeforces 161D Distance in Tree 树形dp

    题目链接: http://codeforces.com/contest/161/problem/D D. Distance in Tree time limit per test 3 secondsm ...

  3. poj2378 树形DP

    C - 树形dp Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:65536KB     64bit ...

  4. 秘密袭击 [BZOJ5250] [树形DP]

    分析: 听说正解是FFT+线段树合并,然而我并不会... 我们来思考其他的方法. 我们要求的是连通块第k大的和 对于某一个连通块,对答案的贡献=val(Rank.K) 我们不好直接算出每个连通块的Ra ...

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

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

  7. 树的直径的求法即相关证明【树形DP || DFS】

    学习大佬:树的直径求法及证明 树的直径 定义: 一棵树的直径就是这棵树上存在的最长路径. 给定一棵树,树中每条边都有一个权值,树中两点之间的距离定义为连接两点的路径边权之和.树中最远的两个节点之间的距 ...

  8. 5.21 省选模拟赛 luogu P4297 [NOI2006]网络收费 树形dp

    LINK:网络收费 还是自己没脑子. 早上思考的时候 发现树形dp不可做 然后放弃治疗了. 没有合理的转换问题的模型是我整个人最大的败笔. 暴力也值得一提 爆搜之后可以写成FFT的形式的计算贡献的方法 ...

  9. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

随机推荐

  1. 四、xadmin自定义插件1

    插件原理: Xadmin中每个页面都是一个AdminView对象返回的HTTPResponse结果. Xdamin插件所做的事情就是其实就是在AdminView执行过程中改变其执行逻辑或是改变其返回的 ...

  2. JSON Web Token 入门教程

    原文地址:http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html JSON Web Token(缩写 JWT)是目前最流 ...

  3. Python-序列化模块-json-62

    序列化模块 Eva_J 什么叫序列化——将原本的字典.列表等内容转换成一个字符串的过程就叫做序列化. 比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给? 现在我们能想到 ...

  4. Python_列表推导式_生成器的表达式_各种推导式_40

    列表推导式: #列表推导式: egg_list = [] for i in range(10): egg_list.append('鸡蛋%s'%i) print(egg_list) egon egg_ ...

  5. 最短路问题 Floyd+Dijkstra+SPFA

    参考博客:https://blog.csdn.net/qq_35644234/article/details/60875818 题目来源:http://acm.hdu.edu.cn/showprobl ...

  6. git的用法步骤讲解

    1.创建全局的本地用户名 git config --global user.name "teamemory" git config --global user.email &quo ...

  7. Tomcat Windows 系统下安装及注意事项

    1 获取Tomcat 安装包  http://tomcat.apache.org/ tar.gz 文件是Linux系统下的安装版本 exe文件是 Windows系统下的安装版本 zip 文件是Wind ...

  8. [转帖]wifi 4G 和 蓝牙的区别

    作者:沈万马链接:https://www.zhihu.com/question/64739486/answer/225227838来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...

  9. [转帖]linux下的CPU、内存、IO、网络的压力测试

    linux下的CPU.内存.IO.网络的压力测试 https://www.cnblogs.com/zhuochong/p/10185881.html 一.对CPU进行简单测试: 1.通过bc命令计算特 ...

  10. java学习之—链表(1)

    /** * 单链表操作 * Create by Administrator * 2018/6/14 0014 * 下午 2:05 **/ public class Link { public int ...