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 ...
随机推荐
- 分享vs低版本开发的项目到VS高版本时遇到的4个小问题解决之记录
分享vs低版本开发的项目到VS高版本时遇到的4个小问题解决之记录 原文首发: http://anforen.com/wp/2017/08/extensionattribute_compilerserv ...
- [蛙蛙推荐]SICP第一章学习笔记-编程入门
本书简介 <计算机程序的构造与解释>这本书是MIT计算机科学学科的入门课程, 大部分学生在学这门课程前都没有接触过程序设计,也就是说这本书是针对编程新手写的. 虽然是入门课程,但起点比较高 ...
- python中各个response使用
Python django中我们经常用的response有django中的 JsonResponse, HttpResponse,还有DRF中的Response 在使用的时候,经常会不知道如何什么时候 ...
- Java开学测试源代码
package sample; import java.io.IOException;import java.io.Serializable;import java.util.Scanner;impo ...
- stl stack用法
栈后进先出 #include<iostream> #include<algorithm> #include<cstdio> #include<stack> ...
- PHP开发web应用安全总结
XSS跨站脚本 概念:恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意用户的特殊目的. 危害: 盗取用户COOKIE信息. 跳转 ...
- 泛函p121可分Hilbert空间都同构于l^2
如何理解最后面两句话, L^2与l^2同构 L^2里面 有理系数多项式 是可数稠密子集 所以L^2可分 可分Hilbert空间都同构于 l^2 傅里叶级数是一个稠密的子集
- SpringMvc的Controller singleton synchronized
SpringMvc的controller是singleton的(非线程安全的) - lvyuanj的专栏 - CSDN博客 https://blog.csdn.net/lvyuanj/article/ ...
- 抓包工具之fiddler
fiddler手机抓包的原理与抓pc上的web数据一样,都是把fiddler当作代理,网络请求走fiddler,fiddler从中拦截数据,由于fiddler充当中间人的角色,所以可以解密https ...
- laravel创建项目
composer create-project --prefer-dist laravel/laravel=5.5.* blog