残虐T3の範囲を考えると、私は最初の問題に退廃ピースソリューションを取ることにしました。
T1都市(都市)
包含と除外方法バッフル+
n個のグループにMの建設チームは、各グループが持っている必要があり、上限値、Cの合計(M-1、N-1)プログラムの種類とは見なされません。
K以上のI番目のグループ、オフ撥容量C(N、I)* C(MI * K-1、N-1)×K iは建設チームに出て対応し、残りMI * n個のグループとチームにkの構成は、各グループが少なくとも一つと結合しない考慮し、少なくとも二つのグループが存在するn個のパケットにこのI-kがK Iよりも大きいがあることを確認します。
書式#include <iostreamの> の#include <CStringの> の#include <cstdioを> に#define MOD 998244353 の#define LL長い長い 使って 名前空間はstdを、 LLのN、M、K、FAC [ 10001000 ]、INVの[ 10001000 ]、facinv [ 10001000 ]、ANS。 LL C(LLのX、LL Y) { 場合(Y> X)戻り 0 ; 戻り FAC [X] * facinv [Y]%MOD * facinv [XY]%MOD。 } int型のmain() { scanf関数(" %LLD%LLD%LLD "、&N、&M、およびK); もし(N>M){ プット(" 0 " )。 リターン 0 ; } FACが[ 0 ] = 1 ; facinv [ 0 ] = 1 ; INV [ 1 ] = 1 。 以下のために(int型 i = 1 ; iは= MAX(N、M)<; I ++のを){ 場合(I =!1)INV [I] =(MOD-MOD / I)* INV [MOD%I]%MOD。 FAC [i]は = FAC [I- 1 ] * I%MOD。 facinv [I] = facinv [I- 1 ] * INV [I]%MOD。 } のために(int型 i = 1 ; iがn = <; iは++ ){ 場合(I&1)ANS =(ANS + C(N、I)* C(MI * K- 1、N- 1))%MOD。 他 ANS =(ANS-C(N、I)* C(MI * K- 1、N- 1)+ MOD)%MOD。 } のprintf(" %のLLDを\ n "、(C(M- 1、N- 1)-ans + MOD)%のMOD)。 リターン 0 ; }
T2の爆撃(爆弾)
受験間違った多くの質問が、私はそれを行うには間違っていませんでした(廃棄物です)
限りパスが到達することができる動きがあるように、我々は、(いくつかのポイントが一緒に塊完成図は、最長の鎖を見つけるために、新しいポイントを構築した後に収縮、各点の深さは、親ノード点+奥行き寸法でなければならない、tarjanが縮小指し)、topu要求最長鎖、またはDFS(DFSなく容易Tと思われます)。
書式#include <iostreamの> の#include <cstdioを> する#include <キュー> 使用して 名前空間はstdを、 構造体ノード { int型、NXTに、 } H [ 4001000 ]、HH [ 4001000 ]。 int型 N、M、NXT [ 4001000 ]、TOT、TET、CNT、[DFN 1001000 ]、[低1001000 ]、S [ 1001000 ]。 int型の上部、NUM、whosは[ 1001000 ]、SZ [ 1001000 ]、デュ[ 1001000 ]、DEP [ 1001000 ]、ANS、NX [ 4001000 ]。 ブール値 である [ 1001000]; INTの最大値(INT X、int型のY) { 戻り X> Yの?X:Y。 } ボイド追加(int型のx、int型のY) { H [ ++ TOT] .TO = Y。 H [TOT] .nxt = NXT [X]。 NXT [X] = TOT。 } ボイドの生成物(int型のx、int型Y) { HH [ ++ TET] .TO = Y。 HH [TET] .nxt = NX [X]。 NX [X] = TET。 } ボイド tarjan(INTX) { [X] DFN =低[X] = ++ CNT。 S [ ++トップ] = xと; ある [X] = 1 。 以下のために(int型 I = NXT [X]を、I; I =をH [i]を.nxt){ int型、Y =をH [i]は.TO。 もし(!DFN [Y]){ tarjan(Y)。 低[X] = 分(低[x]は、低[Y])。 } そう であれば(ある低[Y])を[X] = 分(DFN [Y]、[x]は低いです)。 } もし(DFN [X] == 低[X]){ NUM ++ 。 しばらく(1 ){ int型 TMP = S [top-- ]。 ある [TMP] = 0 ; 玉葉[TMP] = NUM。 SZ [NUM] ++ ; もし(X == tmp)にブレーク。 } } } ボイドtopu() { キュー < INT > Q。 用(int型 I = 1 ; I <= NUM iが++ ) 場合(DU [I] == 0)q.push(I)、DEP [I] = SZ [i]は、ANS = MAX(ANS、DEP [I ]); 同時に(q.size()){ int型のx = q.front(); q.pop()。 以下のために(int型 I = NX [X]を、I; I =のHH [i]が.nxt){ int型、Y =のHH [i]は.TO。 デュ[Y] - 。 DEP [Y] = MAX(DEP [Y]、DEP [X] + SZ [Y])。 ANS = MAX(ANS、DEP [Y])。 もし(!q.push(Y)デュ[Y])。 } } } int型のmain() { scanf関数(" %D%dの"、&N、&M)。 int型のuを、V。 以下のための(int型I = 1 ; I <= M; iは++ ){ scanf関数(" %d個の%のD "、&U、およびV)。 (V、U)を追加します。 } のために(int型 I = 1は iが++; iがn = < ) であれば(!tarjan(I)DFN [I])。 以下のために(int型私= 1 ; iが<= N; iが++ ){ ため(INT J = NXT [I]; J; Jは= H [J] .nxt){ int型、Y = H [J] .TO。 もし(whosは[I] =!玉葉[Y]){ 広告(玉葉[I]、whosは[Y])。 デュ[whosは[Y]++ ; } } } topu()。 printf(" %d個の\ n " 、ANS)。 }