[コメットOJ - コンテスト#6 D] [48D 2280]別のチャネルツリーの互いに素なセットタイトル_

もう一つの問題は、道路の木

効果の対象

データ範囲


問題の解決策

この質問は一見で見つけることができ、私たちの答えは2例に分かれています。

最初の非収束のルートにあり、収束は、ルートノードに第二あります。

ラウンドの終わりを列挙するためのいくつかの試みの最初に、プログラムの最初のラウンドの終わりの数は$ I $ $のf_i $であると仮定すると、次に、答えは常に$ \和の\ limits_ {i = 1} ^ある{N - 1} iが時間のf_i $を\します。

この$のf_i $を見つけることが明らかにできない....

F _ jは$ - さらに、サフィックスがこのいまいましい事を考えると、それは聞いて良さそうです、私_ = \合計\ limits_ {J =} ^ {1} N $ gがあります。

我々はポイントに等しい深さに相当する議論として、$順BFS $を考えることは難しいことではありません。

収束のルートノードの場合を考えるだけではなく。

連続したゾーン、実際には、彼らは$ iの時間の値よりも小さくない$され、あなたが値を選択することができない、ことがわかりました。

それは我々が増加を列挙ラウンド数と一緒に、これらの連続区間は例いくつかの統合があるでしょう。

以下のためのように、それをマージするには?実際には、その$のLCAの$深さに隣接する2つの点に係る関連それは、深さの差は、ラウンド数と正確に一致される、(これら2点の深さと等しくなるように)場合、我々は、マージ操作を実現します。

これは、非ルート合流への完璧なソリューションではありません。

収束することになって、ルートノードを考えてみましょう。

実は相当で、ラウンドの増分の数、$以下のすべての深さとして私はポイントは一つだけを選択することができます$、および根を組み合わせ戦略と同等です。

ショートパスユニバーサルで互いに素-設定を十分に維持します。

コード

#include <ビット/ STDC ++ H> 

に#define N 200010 

名前空間stdを使用。

[N << 1]、NXT [N << 1]、TOTにINTヘッド[N]、。

構造体ノード{ 
	int型のX、Y。
}。

ベクター<ノード> V [N]。

キュー<整数> Q; 

[N] INV [20] [N]、G [N]、F [N]、S [N]、DEP [N]、DIC [N]、N、F INT。

const int型のmod = 998244353; 

typedefの長い長いLL。

するchar * P1、P2 *、BUF [100000]。

#define NC()(P1、P2 == &&(P2 =(P1 = BUF)+関数fread(BUF、1、100000、STDIN)、P1 == P2)EOF:* P1 ++)

int型RD(){ 
	int型X = 0、F = 1。
	チャーC = NC()。
	一方、(C <48){ 
		IF(C == ' - ')
			、F = -1。
		C = NC()。
	} 
	一方、(C> 47){
		X =(((X << 2)+ X)<< 1)+(C ^ 48)、C = NC()。
	} 
	のx * Fを返します。
} 

INT qpow(int型のx、int型のY){ 
	int型ANS = 1。
	一方、(Y){ 
		{(Y&1)であれば
			ANS =(LL)ANS * X%MOD。
		} 
		Y >> = 1。
		X =(LL)X * X%MOD。
	} 
	戻りANS。
} 

インラインボイド追加(int型のx、int型のY){ 
	[++ TOT = Yであり; 
	NXT [TOT =頭部[X]。
	ヘッド[X] = TOT。
} 

int型LCA(int型のx、int型のY){ 
	IF(DEP [X] <DEP [Y])    
		スワップ(X、Y)
	以下のために(INT I = 19;〜I; I - ){ 
		IF(DEP [F [i]が[X]]> = DEP [Y]){ 
			X = F [i]が[X]。
		} 
	} 
	(x == y)の場合 
		Xを返します。
	以下のために(INT I = 19;〜I; I - ){ 
		IF(!F [i]が[X] = F [i]を[Y]){ 
			X = F [i]が[X]。
			Y = F [i]を[Y]。
		} 
	} 
	[0] [x]はFリターン。
} 

ボイドDFS(INT P、INT FA){ 
	V [DEP [P]一back((ノード){1、P。}); 
	F [0] [P] = FA。
	以下のために(INT i = 1; iは<= 19; I ++){ 
		F [i]が[P] = F [I - 1] [F [I - 1] [P]]。
	} 
	のための(INT I =ヘッド[P]; I; I = NXT [I]){ 
		IF(の[I] = FA!){ 
			DEP [する[I] = DEP [P] + 1。
			DFS([i]は、pまで)。
		} 
	} 
} 

ボイドBFS(){ 
	一方(q.empty()!)
		q.pop(); 
	q.push(1)。
	int型CNT = 0; 
		q.pop();
	しばらく(!q.empty()){
		INT X = q.front()。
		DIC [++ CNT] = xと; 
		以下のために(INT I =ヘッド[X]; I; I = NXT [I]){ 
			IF(の[I] = F [0] [X]!){ 
				q.push(の[I])。
			} 
		} 
	} 
	のために(INT i = 1; iがn <; iは++){ 
		IF(DEP [DIC [I]] == DEP [DIC [I + 1]]){ 
			V [DEP [DIC [I] - DEP [LCA(DIC [I]、DIC [I + 1])]]一back((ノード){DIC [i]は、DIC [I + 1]})。
		} 
	} 
} 

int型の検索(INT X){ 
	リターンF [X] == X?X:F [X] =(F [X])を見つけます。
} 

メインINT(){ 
	N = RD()。
	以下のために(INT i = 1; iが<= N; iは++){ 
		F [I] = I。
		S [I] = 1。
	} 
	{ため(iは++; iがn = <I = 2 INT) 
		)(INT X = RDと、
		(X、i)を追加します。
		追加(I、x)は、
	}
	DFS(1、1)。
	BFS(); 
	INV [0] = 1; 
	(; iが<= N I ++はiは1 = INT)のための
		[I] = qpow INV(I、MOD - 2)。

	//ため(; iがn = <; I = 0 int型私は++){ 
	//のprintf( "%dの"、INV [I])。
	//} 
	//プット( "")。

	INT MDL = qpow(2、n)は、
	以下のために(INT i = 1; iがn <; iは++){ 
		グラム[I] =(MDL - N - 1 + MOD)%MOD。
		INT LEN = V [i]を.size()。
		以下のために(; J <LEN、INT J = 0 J ++){ 
			int型のx = V [i]は[J] .X、YはV [i]は[J] .Yを=。
			X =検索(X)、Y =(y)を見つけます。
			IF(X = Y!){ 
				MDL =(LL)のMDL *のINV [S [X] + 1]%MOD * INV [S [Y] + 1]%MOD。
				F [X] = Y。S [Y] + = S [X]。
				MDLは=(LL)のMDL *(S [Y] + 1)%MOD。
			}
		} 
	} 
	INT ANS = 0。
	{(; iがN <I ++は、I = 1 INT)のための
		ANS =(ANS +(LL)(G [I] - G [I + 1] + MOD)%MOD * I%MOD)%MOD。
	} 
	COUT << ANS << ENDL。
	0を返します。
}

概要:良い質問良い質問、この質問は、ギャップを埋める考え。そのための鍵は、鍵となる問題の範囲、にマージするようにのみ、明確に考えるように一つのことを選択することができ、いくつかのこのセクションのための考える力、です。

おすすめ

転載: www.cnblogs.com/ShuraK/p/11241290.html