[AtCoder] AtCoderグランドコンテスト035問題解決レポート

競争を入力するにはここをクリック

\(\):XORサークル(問題の表面を見るにはここをクリックしてください

:一般的な質問の意味は、あなた\(N- \)番号を、彼らは、リングにリングを置くことができるかどうかを尋ねられたように隣接する2つの位置の排他的論理和値上の各位置。

最初に考慮されていない\(0 \) 我々は最初の数はリングであることを前提としてい\(A_1 \) 秒数である(A_2 \)\は、第3の数\(A_3 = A_1 \ XOR \ A_2 \ 、第四の数\(A_4 A_2 = \ XOR \ A_3 = A_1 \)

法律上のループがしなければならない上など、それは、言うことです(A_1、A_2、A_1 \ \ XOR \ A_2 \) 3を繰り返します。

Tidyの、それが満たされることです。

  • 示される3つだけの数字の合計、\(X、Y、Zの\)
  • 各の出現数として。
  • \(X \ XOR \ Y = Z \)

その後、我々は特別な考慮する必要があります\(0 \)

まず、\(N- \)\(0 \)は必ずしも正当な。

第二に、場合にのみ(0 \)\と別の番号の\(X \) および\(X \)出現回数がさ(0 \)\その倍の数だけでなく、法的には(実際には、この状況がトップに起因することができます表示されます)。

それはそれが可能であるべきです。\(AtCoder \)緊急データに、そこにあれば\(ハック\)のデータは、以下のコメントエリアにメッセージを残すことができます。

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
using namespace std;
int n,a[N+5],s[N+5];
class FastIO
{
    private:
        #define FS 100000
        #define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
        #define tn (x<<3)+(x<<1)
        #define D isdigit(c=tc())
        char c,*A,*B,FI[FS];
    public:
        I FastIO() {A=B=FI;}
        Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
        Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
}F;
int main()
{
    RI i,t=0;for(F.read(n),i=1;i<=n;++i) F.read(a[i]);
    for(sort(a+1,a+n+1),i=1;i<=n;++i) s[i]=a[i];t=unique(s+1,s+n+1)-s-1;//求出有几种数
    if(!a[1]&&t==1) return puts("Yes"),0;if(n%3||t>3) return puts("No"),0;//分别特判有n个0、n非3的倍数、数的种类超过3种的情况
    for(i=1;i<n/3;++i) if(a[i]^a[i+1]) return puts("No"),0;//判断第一种数是否占所有数的1/3
    for(i=n/3+1;i<n/3*2;++i) if(a[i]^a[i+1]) return puts("No"),0;//判断第二种数是否占所有数的1/3
    for(i=n/3*2+1;i<n;++i) if(a[i]^a[i+1]) return puts("No"),0;//判断第三种数是否占所有数的1/3
    return puts((a[1]^a[n/3+1])==a[n]?"Yes":"No"),0;//判断是否符合异或条件
}

\(Bの\) でも、度(問題の表面を見るにはここをクリックしてください

大雑把な質問の意味は:学位のすべての点が偶数になるようにあなたは、各エッジの方向を決定するので、あなたのマップを与えます。

両側の奇数は確かに何の解決策ではありません見つけるために、最初の文に難しいことではありません解決策を考えてみません、それは解決可能であっても一定です。

解決策は、我々は最初のアートワークでは、スパニングツリー、その後、非ツリーエッジがちょうど与えられた方向を見つけた場合。

次に、私たちは木をトラバース。

各点について、のは、すべての子ノードの処理を完了させ、その後、この点だけと親ノード間のエッジの方向性を検討します。

現在のノードが奇数の方向である場合、つまり、彼の父の側に、そうでなければ、方向は、現在のノードの側にあります。

このようにして、我々はルート以外のすべてのノードがさえ程度であることを確認することができます。そしてエッジの総数は、偶数番目のルートで、偶数です。

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
using namespace std;
int n,m,ee,d[N+5],lnk[N+5];struct edge {int to,nxt;}e[N<<1];
class FastIO
{
    private:
        #define FS 100000
        #define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
        #define pc(c) (C==E&&(clear(),0),*C++=c)
        #define tn (x<<3)+(x<<1)
        #define D isdigit(c=tc())
        int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
    public:
        I FastIO() {A=B=FI,C=FO,E=FO+FS;}
        Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
        Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
        Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
        Tp I void writeE(Con Ty& x,Con Ty& y) {write(x),pc(' '),write(y),pc('\n');}
        I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
}F;
template<int SZ> class UnionFindSet//并查集用于找生成树时判连通性
{
    private:
        int f[SZ+5];
        I int getfa(CI x) {return f[x]?f[x]=getfa(f[x]):x;}
    public:
        I void Union(CI x,CI y) {f[getfa(x)]=getfa(y);}
        I bool Identify(CI x,CI y) {return getfa(x)==getfa(y);}
};UnionFindSet<N> U;
I void dfs(CI x,CI lst=0)//遍历树
{
    RI i;for(i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&(dfs(e[i].to,x),0);//先处理子节点
    lst&&(d[x]?F.writeE(x,lst):(d[lst]^=1,F.writeE(lst,x)),0);//根据当前节点度数奇偶性确定到父节点边的方向
}
int main()
{
    RI i,x,y;if(F.read(n,m),m&1) return puts("-1"),0;
    for(i=1;i<=m;++i) F.read(x,y),U.Identify(x,y)?
        (F.writeE(x,y),d[x]^=1):(U.Union(x,y),add(x,y),add(y,x));//生成树上边在树上连边,非树边随便定方向
    return dfs(1),F.clear(),0;
}

\(C \) スコーレムXORツリー(問題の表面を見るにはここをクリックしてください

一般的な問題の意味:ある\(2N \)ポイント、\(私は\)\(N + Iが\)ポイントは右である\(私は\) すべてのためになるように、スパニングツリーにあなたを構築するには、\(私は\)\(N + Iが\)ツリーパスが排他的論理和である\(私は\します)

いずれかのために、最初に考える\(2X \)\(2×+。1 \) 満足\((2×)\ XOR \(1 + 2×)= 1 \)

だから我々は、すべてのことができます\(\ FRAC N2 \ rfloor \ lfloor X- \ル\)でも、>( - \((2倍) ×2 + 1) - >(1) - >(N + 2回) - >(N + 1 + 2回)\)

そのためノード注意\(1 \)\(N-1 + \) 我々も((2) - )を\ \ >(N + 1) とすることができます。

上記の手順によると、ために\(N- \)奇数である、我々は処理を終了しました。

しかし、場合\(N \)があるとしても、そのために\(N \)\(2n個\) 2つのノードが、私たちは建物を完了していない、と彼らは以前のルーチンに従って構築することができません。

考えてみて、今の問題は、スパニングツリー上の2点を見つけることです、ツリーパスは、彼らがXOR値となるよう\(N \) そして私たちは聞かせすることができます\(N \)\(2N \)をそれぞれ2点の息子として。

重要なのは、ここでのスパニングツリーは非常に特別です!XORツリーパス値は、パスのルートノードへの2つの点の排他的論理和した後、XORである\(1 \)

限りオープンバレルを簡単に検索することができるよう。

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define add(x,y) (a[++cnt]=x,b[cnt]=y,addE(x,y),addE(y,x))
#define addE(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
using namespace std;
int n,cnt,ee,s[2*N+5],p[N<<1],lnk[2*N+5],a[N<<1],b[N<<1];struct edge {int to,nxt;}e[N<<2];
I bool dfs(CI x,CI lst=0)//找树上路径异或为n的两个点
{
    if(p[n^s[x]^1]) return add(n,p[n^s[x]^1]),add(x,n<<1),true;p[s[x]]=x;//先查询是否存在对应点,若有则建边返回true,没有则刷新桶
    for(RI i=lnk[x];i;i=e[i].nxt) if(e[i].to^lst&&(s[e[i].to]=s[x]^(e[i].to%n),dfs(e[i].to,x))) return true;//处理子节点
    return false;//找不到返回false
}
int main()
{
    RI i,j,t;if(scanf("%d",&n),n==1) return puts("No"),0;//特判n=1的情况输出无解
    for(i=2;i<n;i+=2) add(i,i+1),add(i+1,1),add(1,n+i),add(n+i,n+i+1);add(2,n+1);//对于每一对相邻的数,按套路建图
    if(!(n&1)&&!dfs(s[1]=1)) return puts("No"),0;//如果第n个点和第2n个点找不到位置安放,输出无解
    for(puts("Yes"),i=1;i<=cnt;++i) printf("%d %d\n",a[i],b[i]);//输出
    return 0;
}

\(D \) 追加および削除(問題の表面を見るにはここをクリックしてください

:大雑把な質問の意味、あなたが番号を削除することができますたびにシーケンスを与えるために、その辺の数とこの数の値は、最小2の数と、残りの最後。

私たちは考えることができます\(DFS \を)

溶液は、現在の間隔の設定\([L、R&LT] \) 左点を計算する間隔\(TL \)回、右エンドポイントが算出される\(TR \)回。

その後、我々はこの範囲内の数は最終的に削除された列挙することができます(私は\)\、その後、回数は次のことが計算された\(TL + TR \)

我々は、次に、再帰的にサブセクション処理\([L、I] \ ) と\([I、R&LT] \) 統計的最小にします。

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 18
#define LL long long
#define RL Reg LL
#define CL Con LL&
#define INF 1e18
#define Gmin(x,y) (x>(y)&&(x=(y)))
using namespace std;
int n,a[N+5];
I LL dfs(CI l,CI r,CL tl,CL tr)//dfs
{
    if(r-l==1) return 0;RL t,res=INF;//若只剩左右端点,返回0
    for(RI i=l+1;i^r;++i) t=dfs(l,i,tl,tl+tr)+dfs(i,r,tl+tr,tr)+a[i]*(tl+tr),Gmin(res,t);//枚举最后被删除的数,递归子区间
    return res;//返回答案
}
int main()
{
    RI i;for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d",a+i);//读入
    return printf("%lld",dfs(1,n,1,1)+a[1]+a[n]),0;//求解
}

\(E \) 開発(問題の表面を見るにはここをクリックしてください

このタイトルはされる(BZT \)\神々は時にシミュレートされたトーナメントのタイトルに移動しました。

:解釈は、このブログ見ることができます[2019年8月11日朝慈渓シミュレーションゲームT2] 17キロの重量文明(セブンティーン)を

\(F \) 二つのヒストグラム(問題の表面を見るにはここをクリックしてください

一般的な質問の意味:与えられた(N×m個の\)\行列、それぞれの行を決定\(k_i∈[0、M] \)の各列の\(l_i∈[0、N - ] \) 行列は\((i、j)は\ ) の位置の値がされた\([J \ルK_I] + \ [Iルがl_j \]) 多くの異なる行列が尋ねてきました。

私たちは、のためにシーケンスのセットを考える\(K、L \)同じ行列式の結果と同様の構成を、マトリックスの異なる構成をするよう、それらを表現するための統一された方法を見つけるために、。

次いで、存在する場合、見出すことができる図面(Xの\)\\(Y軸\)を満たすが、\(K_x + 1 = Y-の\と\ L_yはX- \ =) 我々はでき\(k_x \)プラス\(1 \を)、\ (L_y \)保存\(1 \)

だから我々は、どれだけ多くのグループを知りたい\(K、L \)をそこにするように、(X、Yの\)は\上記の基準を満たしています。

これと除外。

存在下で使用することである\(X、Yの\)ログを\(\ GE0 \)番号スキーム、マイナスの対数(\ \ GE1が\)番号スキーム、数と結合(\ GE2 \)\番号スキーム、ように。

取得するための必要性を提供(\ GEのX \)\のプログラムの数、我々最初の\(K \)選択\(X \)の位置は、\(Lの\)で撮影\(X \)の位置、ちょうど残りを埋める、それは次のようになります。

\ [C_N ^ X * A_M ^ X *(N + 1)^ {MX} *(M + 1)^ {NX} \]

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 500000
#define X 998244353
#define swap(x,y) (x^=y^=x^=y)
#define Qinv(x) Qpow(x,X-2)
#define A(x,y) (1LL*Fac[x]*IFac[(x)-(y)]%X)
#define C(x,y) (1LL*A(x,y)*IFac[y]%X)
#define Inc(x,y) ((x+=(y))>=X&&(x-=X))
using namespace std;
int n,m,Fac[N+5],IFac[N+5],Pn[N+5],Pm[N+5];
I int Qpow(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
int main()
{
    RI i,t,ans=0;scanf("%d%d",&n,&m),n>m&&swap(n,m);
    for(Fac[0]=Pn[0]=Pm[0]=i=1;i<=m;++i)//预处理
        Fac[i]=1LL*Fac[i-1]*i%X,Pn[i]=1LL*Pn[i-1]*(n+1)%X,Pm[i]=1LL*Pm[i-1]*(m+1)%X;
    for(IFac[m]=Qinv(Fac[m]),i=m-1;~i;--i) IFac[i]=1LL*IFac[i+1]*(i+1)%X;
    for(i=0;i<=n;++i) t=1LL*C(n,i)*A(m,i)%X*Pn[m-i]%X*Pm[n-i]%X,Inc(ans,i&1?X-t:t);//容斥
    return printf("%d",ans),0;//输出答案
}

おすすめ

転載: www.cnblogs.com/chenxiaoran666/p/AtCoderAGC035.html
おすすめ