[Bzoj4026] DCは愛する番号Theory_社長ツリー_ _オイラー関数の素因数分解

dcは数論を愛しています

トピックの効果:dCの数秒後、BZOJ上のすべてのトピックは、孟孟ダを感じ、破壊、水資源の問題を節約するために、例えば、水の問題を思い付きました。正の整数Aの配列の長さnが与えられ、時間クエリQがあり、φの製品のすべての要素の範囲内の各クエリ(φ(n)はカウント数1〜N Nプライム付きの代表)。答えは大きいかもしれないので、それほどのmod 10 ^ 6 + 777に答えるようにしてください。(力によってこの問題は、すべての照会オペレーションLは、rは、最初に、クエリlastansへのXOR回答にlastans = 0が必要)

データ範囲:1 <= N <= 50000、1 <= Q <= 100000、。1 <=あい<^ = 10 6。


ソリューション:

しません.....

私は$話したリアライズlijinnn $を聞きました。

そこは非常に、非常に重要なプロパティがあり、その後、見つからない場合は、単純に行うことはできません。

私たちは暴力に従事する方法を検討する:各完全スキャンを再び、その後、統計的な答え。

これは、あまりにも暴力的です....我々は、最適化を最適化します。

私たちが知っているので、この方法では、最高$ 7の長さを開くには、それぞれの場所は、$配列は、素因数の現在位置を表します。

$ \ varphi(N)= N * \ PRODの\のlimits_ {P_I | N} \ FRAC {P_I - 1} {P_I} $。

この複雑さは(7 N ^ 2 \回)$ $ Oです。

再最適化の最適化?

私たちは、左の各のために、私は、現在のポイントの左端の右側に表示される各品質係数の左端の位置を維持することができることを見出しました。

アレイ全体の上に第一のスイープが最初に各素数のための$ 1 $で左の点の位置を見つける、のは、一番左に表示されます。

各、左から右にポイントを移動品質係数値のすべての答えは、このクエリは、次に、$ O(N)である配列、に対応するように左端点でチェックされ左端点の現在位置を更新しますの$。

OK、今の$ O(N ^ 2)$の複雑さのために、フォーカスは、それぞれの場合において、最も左の位置を左点以下で品質係数を維持しないことです。

その正の解はまだ出てきません!

私たちは、左のポイントは、一度すべての動きは、たったの$ 7 $の最大の値を変更することが判明し、残りの値は同じです。

これをどう維持することができますか?これは、同じ、ごくわずか異なるがたくさんあります

木の会長はええ、私たちは、左のツリーごとに委員長を開き、直接ちょうど前記アレイを維持することがポイント。

どのようにそれを維持するには?

- 私が一番左の位置$ jは$、ツリー$ jは$位置$の後、議長は、* = \ FRAC {Pの左側を$ $での素数$ pが$がある場合、最初の$ iについては$、会長の星の木であります1} {P} $、その後社長ツリーノードは間隔を支配し、すべての製品番号を維持します。

しかしながら、各個々の素因数分解点の$ O(N \のSQRT {a_iを})$、我々は数で質量を前処理し、その後、列挙素数が大きく複雑であった(NLN \高調波シリーズの$ OでありますN)$。

ツリーの複雑さの議長は$ O(nlogn)$、それぞれ$ O(loglogn)$、総複雑性は$ O(nlognloglogn + NLNする\ n)$であるとです。

コード

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

に#define N 50010 

名前空間stdを使用。

const int型のmod = 1000777; 

typedefの長い長いLL。

ベクター<整数> V [1000010]。

int型、[1000010]プライムCNT。

VISブール[1000010]。

INT [1000010]予め、BFR [N]、[N]。

int型のLS [N * 200]、RS [N * 200]、合計[N * 200]、根[N * 200]、TOT。

する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。
} 

ボイドのinit(){ 
	ための式(I = 2 int型、iは<= 1000000; iは++){ 
		IF(VIS [I]!)
			プライム[++ CNT] = I。
		用(INTのJ = 1; J <= CNT &&(LL)iは素数[j]を* <= 1000000; J ++){ 
			VIS [i *が素数[J] = TRUE; 
			IF(I%プライム[j] == 0){ 
				破ります。
			} 
		} 
	} 
} 

ボイド更新(int型のx、int型のVal、INT L、のint R、int型プリ、INT&P){
	P = ++ TOT; 
	LS [P] =のLS [事前]。
	RS [P] = RS [事前]。
	和[P] =(LL)の和[事前] *ヴァル%のMOD。
	IF(L == R){ 
		リターン。
	} 
	INT半ば=(L + R)>> 1。
	IF(X <= MID)
		更新([事前] X、ヴァル、L、中間、LS、LS [P])。
	そうでなければ
		更新(X、ヴァル、中間+ 1、R、[事前] RS、RS [P])。
} 

int型の照会(int型のx、int型のY、int型のL、R INT、INT P){ 
	(P!){場合に
		1を返します。
	} 
	場合(X <= L && R <= Y){ 
		戻り和[P]。
	} 
	INT ANS = 1、ミッド=(L + R)>> 1。
	IF(X <= MID)
		ANS =(LL)ANS *クエリ(X、Y、L、中間、LS [P])%MOD。
	(ミッド<y)の場合
		ANS =(LL)はANS *クエリ(X、Y、中間+ 1、R、RS [P])%MOD。
	ANSを返します。
} 

int型のmain(){ 
	int型N = RD()、M = RD()。
	以下のために{(INT i = 1; iが++; iが<= N) 
		[I] = RD()。
	} 

	BFR [0] = 1。
	以下のために(INT i = 1; iが<= N; iは++){ 
		BFR [I] =(LL)BFR [I - 1] * [I]%MOD。
	} 

	のinit(); 
	{(;私は= CNTを<I ++はiは1 = INT)のための
		(INT J =プライム[I]; J <= 1000000; J + =プライム[i])とするために、{ 
			V [J] .push_back(I) ; 
		} 
	} 

	// COUT <<プライム[CNT] << ENDL。

	//ため(; iがn = <; I = 1 int型私は++){ 
	// INT LEN = V [i]は]サイズ()。
	//のための(INT J = 0; J <LEN; J ++){ 
	//のprintf( "%dの"、プライム[V [I]、[J])。
	//} 
	//プット( "")。
	//}
 
	和[0] = 1。

	以下のために(INT i = 1; iが<= N; iは++){ 
		int型LEN = V [i]は]サイズ()。
		用(int型J = 0; J <LEN; J ++){ 
			IF(予備[V [I]、[J]]){ 
				更新(予備[V [I]、[J]、( LL)プライム[V [I]、[J]] * qpow(プライム[V [I]、[J]] - 1、MOD - 2)%のMOD、1、nは、(ルート[I] ?ルート[I]:ルート[I - 1])、ルート[I])。
			} 
			更新(I、(LL)(プライム[V [I]、[J]] - 1)* qpow(プライム[V [I]、[J]、MOD - 2)%のMOD、1 、nは、(?ルート[i]はルート[I]:ルート[I - 1])、ルート[I])。
			//のprintf( "くそ%D \ n"は、V [I]、[J])。
			プレ[V [I]、[J] = I。
		} 
	} 

	// COUT <<和[ルート[1] << ENDL。
	// COUT <<(LL)の和[ルート[1]] * 3%MOD * qpow(2、MOD - 2)%のMOD << ENDL。

	// COUT <<和[ルート[4]] << ENDL。
	// COUT <<(LL)の和[ルート[4] * 2 * 6 * 4%MOD * qpow(3、MOD - 2)%MOD * qpow(2、MOD - 2)%のMOD * qpow(5、 MOD - 2)%MOD * qpow(7、MOD - 2)%のMOD << ENDL。

	//プット( "ファック"); 

	int型lastans = 0; 
	以下のために(INT I = 1; I <= M; iは++){ 
		int型のx = RD())(Y = RD。
		X ^ = lastans、Y ^ = lastans。
		IF(X> Y){ 
			lastans = 1。
			プット( "0"); 
			持続する; 
		} 
		// COUT <<(LL)BFR [Y] * qpow(BFRの[X - 1]、MOD - 2)%のMOD << ENDL。
		lastans =(LL)BFR [Y] * qpow(BFRの[X - 1]、MOD - 2)%MOD *クエリの(x、y、1、nは、ルート[Y])%MOD。
		printf( "%d個の\ n"、lastans)。
	} 
	0を返します。
}

概要:ああ、プロパティが見つからないことが重要です本当に良い質問。ツリーの使用の会長も非常に巧妙です。

おすすめ

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