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 ...
随机推荐
- LeetCode 832. Flipping an Image
Given a binary matrix A, we want to flip the image horizontally, then invert it, and return the resu ...
- 根据指定条件使CheckBox 无法选中
var trList = $("#tab1").children("tr")for (var i=0;i<trList.length;i++) {var ...
- 007-迅雷定时重启AutoHotkey脚本-20190411
;; 定时重启迅雷.ahk,;;~ 2019年04月11日;#SingleInstance,forceSetWorkingDir,%A_ScriptDir%DetectHiddenWindows,On ...
- c++入门之字符相关入门
先上代码: # include "iostream" # include "string" //# define BYTE char//注意,这里没有分号,且# ...
- JavaWeb连接SQLServer数据库并完成一个登录界面及其功能设计。
一.JDBC连接SQLserver数据库的步骤: 1.下载SQLserver的JDBC驱动文件——Microsoft JDBC Driver 4.0 for SQL Server 2.例如下载得到的文 ...
- git reset的用法
git reset三个选项 --mix,--hard,--soft 数据 针对每个选项都是操作这个文件. [root@centos demo]# git init Initialized empty ...
- 解决selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home
解决方案: 1.查看浏览器当前版本:chrome://version/. 2.到https://sites.google.com/a/chromium.org/chromedriver/downloa ...
- Oss文件存储
包含文件的上传下载和生成临时的url # -*- coding: utf-8 -*- import os import oss2 import configparser from Config imp ...
- centos 6.9:device eth0 does not seem to be present
VMware上安装centos6.9,克隆一个新虚机,网卡不能桥接获得宿主机网络地址. https://blog.csdn.net/xiaobei4929/article/details/405152 ...
- IdentityServer4【Introduction】之概括
The Big Picture 大多数现代应用看起来都像下面的样子: 大多数的交互是下面这样: 浏览器与web应用之间的通信 web应用和web APIs之间的通信(这两者有时是独立的,有时是有用户参 ...