1. 程式人生 > >[帶標號無向連通圖計數 容斥原理 多項式求逆 多項式求ln 模板題] BZOJ 3456 城市規劃

[帶標號無向連通圖計數 容斥原理 多項式求逆 多項式求ln 模板題] BZOJ 3456 城市規劃

可以通過容斥求出答案的表示式

fi=2C2ij=1i1Cj1i1fj2C2ij
其中前一部分表示i個點任意連邊 後半部分列舉1所在的連通塊然後容斥掉 j=1ifj(j1)!2C2ij(ij)!=2C2i(i1)!
這是個卷積的形式 分別令
A=i=1nfi(i1)!xi
B=i=0n2C2ii!xi
C=i=1n2C2i(i1)!xi
所以 AB=C
那麼 ACB1(modxn+1)
這個多項式求逆下就好了

UPD:
這裡提到了另一種簡潔的理解方法
n個標號點任意無向圖的EGF為

G=i=0n2C2ii!xi
n個標號點連通無向圖的EGF為
F
=i=1nfii!xi

根據eF(x)的組合意義 也就是集合和劃分的關係 我們得G=eF
也就是F=lnG
多項式求ln? 把兩邊同時取導數
F(x)=G(x)G(x)
也就是一個 求導 求逆 乘法 積分
我們發現這和之前的方法是一致的
實際上 A=Fx,B=G,C=Gx
AB=C就是FG=G 只不過等式兩邊都乘了x
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;

const int
N=600005; const int P=1004535809; const int G=3; inline int Pow(ll a,int b){ ll ret=1; for (;b;b>>=1,a=a*a%P) if (b&1) ret=ret*a%P; return (int)ret; } int num; int w[2][N]; inline void Pre(int n){ num=n; int g=Pow(G,(P-1)/num),invg=Pow(g,P-2); w[0][0]=w[1][0]=1; for (int i=1;i<num;i++) w[0
][i]=(ll)w[0][i-1]*invg%P,w[1][i]=(ll)w[1][i-1]*g%P; } int R[N]; inline void FFT(int *a,int n,int r){ for (int i=0;i<n;i++) if (i<R[i]) swap(a[i],a[R[i]]); for (int i=1;i<n;i<<=1) for (int j=0;j<n;j+=(i<<1)) for (int k=0;k<i;k++){ ll x=a[j+k],y=(ll)w[r][num/(i<<1)*k]*a[j+i+k]%P; a[j+k]=(x+y)%P; a[j+i+k]=(x+P-y)%P; } if (!r) for (int i=0,inv=Pow(n,P-2);i<n;i++) a[i]=(ll)a[i]*inv%P; } inline void GetInv(int *a,int *b,int n){ static int tmp[N]; if (n==1) return void(b[0]=Pow(a[0],P-2)); GetInv(a,b,n>>1); for (int i=0;i<n;i++) tmp[i]=a[i],tmp[n+i]=0; int L=0; while (!(n>>L&1)) L++; for (int i=1;i<(n<<1);i++) R[i]=(R[i>>1]>>1)|((i&1)<<L); FFT(tmp,n<<1,1); FFT(b,n<<1,1); for (int i=0;i<(n<<1);i++) tmp[i]=(ll)b[i]*(2+P-(ll)tmp[i]*b[i]%P)%P; FFT(tmp,n<<1,0); for (int i=0;i<n;i++) b[i]=tmp[i],b[n+i]=0; } int n,m; ll fac[N]; int A[N],B[N],C[N],invB[N]; int main(){ freopen("t.in","r",stdin); freopen("t.out","w",stdout); scanf("%d",&n); for (m=1;m<=n;m<<=1); Pre(m<<1); fac[0]=1; for (int i=1;i<=n;i++) fac[i]=fac[i-1]*i%P; for (int i=0;i<=n;i++) B[i]=(ll)Pow(2,((ll)i*(i-1)>>1)%(P-1))*Pow(fac[i],P-2)%P; for (int i=1;i<=n;i++) C[i]=(ll)Pow(2,((ll)i*(i-1)>>1)%(P-1))*Pow(fac[i-1],P-2)%P; GetInv(B,invB,m); FFT(invB,m<<1,1); FFT(C,m<<1,1); for (int i=0;i<m<<1;i++) A[i]=(ll)invB[i]*C[i]%P; FFT(A,m<<1,0); printf(

相關推薦

[標號連通計數 原理 多項式 多項式ln 模板] BZOJ 3456 城市規劃

可以通過容斥求出答案的表示式fi=2C2i−∑j=1i−1Cj−1i−1∗fj∗2C2i−j 其中前一部分表示i個點任意連邊 後半部分列舉1所在的連通塊然後容斥掉 ∑j=1ifj(j−1)!∗2C2i−j(i−j)!=2C2i(i−1)! 這是個卷積的

【XSY1295】calc n個點n條邊連通計數 prufer序列

ring pre end ctime 節點 splay 按順序 sin algorithm 題目大意   求\(n\)個點\(n\)條邊的無向連通圖的個數   \(n\leq 5000\) 題解   顯然是一個環上有很多外向樹。   首先有一個東西:\(n\)個點選\(k\

leetcode 847. Shortest Path Visiting All Nodes 連通遍歷最短路徑

sel shu turn 判斷 lam 最短 額外 動態 訪問 設計最短路徑 用bfs 天然帶最短路徑 每一個狀態是 當前的階段 和已經訪問過的節點 下面是正確但是超時的代碼 class Solution: def shortestPathLength(self,

LeetCode 547. 朋友圈數量--連通

解析 方法一:DFS 遍歷所有人,對於每一個人,尋找他的好友,找到好友後再找這個好友的好友,這樣深度優先遍歷下去,設定一個visited記錄是否已經遍歷了這個人。 因為如果m個人最多m個朋友圈,設定後visited後,相同的朋友圈會檢測到visited[i]!=0就會不算數

連通中兩點間所有路徑的演算法

http://bbs.csdn.net/topics/360001583 之前在csdn就這個問題發帖求教過,過了幾天沒看到回覆就沒再關心。後來自己設計了一個演算法,在公司的專案中實踐了一下,效果還可以,貼出來供大家參考。演算法要求:1. 在一個無向連通圖中求出兩個給

連通的割點

1. 割點與連通度 在無向連通圖中,刪除一個頂點v及其相連的邊後,原圖從一個連通分量變成了兩個或多個連通分量,則稱頂點v為割點,同時也稱關節點(Articulation Point)。一個沒有關節點的連通圖稱為重連通圖(biconnected graph)。若在連通圖上

poj1737 Connected Graph(n點連通

題目連結 題目描述: 給出n個點,求n個點的無向連通圖 分析: 巨坑啊 經典題目,有兩種方法: 總方案數-不合法方案 nn個點的完全圖有C(n,2)=n(n−1)2C(n,2)=n(n

論】連通的割點

1. 割點與連通度 在無向連通圖中,刪除一個頂點v及其相連的邊後,原圖從一個連通分量變成了兩個或多個連通分量,則稱頂點v為割點,同時也稱關節點(Articulation Point)。一個沒有關節點的連通圖稱為重連通圖(biconnected graph)。若在連通圖上至少刪去k 個頂點才能破壞圖的連通性,則

連通的最小生成樹(c語言版)

完整原始碼地址:[email protected]:hglspace/MinCostSpTree.git 圖例:                     1 普里姆演算法 /*  普里姆演算法:假設N={v,{E}}是連通圖,TE是N上的最小生成樹中邊的集合

連通的最小割點詳解以及java原始碼實現

import java.util.*; /**尋找割點*/ public class FindArt { static class Node { Node(String name) { this.name=name; Childen=new Arra

用Tarjan演算法連通割點&&割邊

/** 割點割邊挺好理解的,割點就是一個無向連通圖,把其中一個點 挖掉剩下的圖不連通,割邊就是把一條邊砍掉不連通 比如:有一個通訊網路,要求一顆炸彈,把這個通訊網路搞得不連通,問 炸哪個點或哪條邊。 Tarjan 演算法實現求割邊

資料結構 之 連通

下列關於無向連通圖特性的敘述中,正確的是 Ⅰ.所有頂點的度之和為偶數Ⅱ.邊數大於頂點個數Ⅲ.至少有一個頂點的度為1 如下圖所示為一個無向連通圖:任何兩個節點之前都是連通的,都存在一條路徑,並且圖中沒有方向。        (1)頂點的度為頂點所連線的邊的個數,無向連通圖中的

poj1523 SPF 連通 割點 關節點 tarjan演算法

SPF Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 5103 Accepted: 2347 Description Consider the two networks shown below.

【ZSTU4213 2015年12月浙理工校賽 D】【雙連通分量tarjan演算法】One-Way Roads 連通確定邊的方向使得全任意兩點間可達

4213: One-Way Roads Time Limit:1 Sec  Memory Limit:128 MB  Special JudgeSubmit:133  Solved:45 Description In the ACM kingdom, there a

bzoj4671: 異或原理+線性基】

解題思路: 考慮容斥,列舉點的集合劃分,強制兩兩集合間的點不連通,集合內的點任意連,若劃分成m個集合,則最後至少有m個連通塊。 而一個m的劃分,在容斥時會被計算∑i=1mSim次(S為第二類斯特林數)。 所以列出容斥係數計算式:∑i=1mSimfi=[m=

【bzoj21115 [Wc2011] Xor 中1道n經過路徑權值的最大異或和(含有環)】

這道題要求從1到n的最大xor和路徑,存在重邊,允許經過重複點、重複邊。 第一行包含兩個整數N和 M, 表示該無向圖中點的數目與邊的數目。 接下來M 行描述 M 條邊,每行三個整數Si,Ti ,Di,表示 Si 與Ti之間存在 一條權值為 Di的無向邊。 圖中可能有重邊或自環。 輸出:僅包含

BZOJ 3456 NTT計數

for bsp clas type cstring sig const signed pow 思路: RT 懶得寫了 //By SiriusRen #include <cstdio> #include <cstring> #inclu

計算無權中兩點間所有的最短路徑

  一、例子 如上圖,節點0到節點5的最短路徑長度為3,有兩條最短路徑: 路徑1:0 — 1 — 4— 5 路徑2:0 — 1 — 2— 5 二、相關名稱 tempLadder:             儲存當前正在計算的路徑 canditStack:          

n個結點的完全的生成樹的個數

頭部閒扯 今天閒來在google搜了一下cantjie,突然發現我的部落格竟然被引用過,很是驚訝。因為雖然僅僅只是過去一年,我現在看我去年寫的部落格,就有種“這寫的什麼垃圾玩意”的感覺,沒想到竟然也會有人瀏覽並引用我的部落格。 想來這個部落格閒置一年多了,突

相關演算法(二):無權的廣度優先遍歷(BFS)-非遞迴版本

核心 採用鄰接表作為圖資料的儲存結構 對訪問過的節點進行記錄,文中採用HashSet實現 採用佇列存放未訪問的子節點,不斷更新佇列 BFS採用佇列實現很簡單,採用遞迴反而更復雜了 本文建立的圖結構如