問題のジョーカー
タイガーとニンニクは良い友人です。
夏は涼しい秋は、到着したトラやニンニクは、新しいエンターテイメントのプロジェクトを持っている、以上です。
タイガーは、シベリアトラの遠いいとこで、カードゲームが勝っ:ゲームに関与する2人のプレーヤーは、小道具は54枚のトランプ、52枚のカードと二つの基本的なジョーカー、またエースとして知られているの一つです。これら二つは赤と黒の王です。それは52枚の基本的なカードスペード、ハート、クラブ、正方形片4つのスーツに分割され、各スーツは、13枚のカード、階層的な順序を有する13枚のカードを持って、それぞれ234 567に従っ8 9 10 2は最低レベルであるJQKAは、Aが最高ランクです。すべての心と側片が赤であるとみなされ、そしてすべてのスペードとクラブは黒であると考えられています。スーツは、我々はディーラーのカードに、このスーツのカードを呼び出し、ハードスポットになりますがあります。
ゲーム開始前に、二人の選手は、6枚のカードの手を持っており、残りの42枚のカードは、デッキを形成します。ゲームのいくつかのラウンドからなるゲームは、各ラウンドの開始前に、手持ちの2人の選手は、カードの数、プレーヤーの上部手、エスケープの他のプレイヤーでした。ただ、選手の数は、テーブルの上に枚数をライセンスするのと同じレベルに配置する必要があり得るだけの選手がいつでも置い切り札に許可されていません取得するために注意を払う、とFLACのプレイヤーが手を持っているカードの総数を超えることはできませんカードを置きます。:プレイヤーは自分のカードの一部、第1選手カード上に積層されたカードは、撮影した別のカード上に積層することができ、以下の条件のうちの少なくとも1つが満たされているがある場合にのみ、反転するかを選択できます
1.このカードとカードのスタックを同じスーツ、およびより高いレベルを持っています。
2.このカードはディーラーのカードで、カードがスタックされていません。
3.このカードは、トランプカードであり、カードと同じ色のスタック。
4.このカードは、切り札であり、それはディーラーやブランド色と同じ色です。すべてのカードがテーブル上に積層された後、あなたがして、テーブル上のカードの数によって上に手を置くことができ、これらのカードはその後、レベルと同じランクのテーブル上の任意のカード(かどうかスタック)でなければなりません手の選手はまだ最初の選手カード上の自分のスタックの一部を選択することができます。最初のプレーヤーはまだテーブルの上にFLACプレーヤーの手のカードの枚数よりも多く配置しないことに注意してください。
FLACのプレイヤーがすることはできませんか、テーブルの上にカードを積み重ねたい、または単にプレイヤーは以上のカードを入れたくないことはできません得ることはありません:と二つの場合のみ1が起こる場合ラウンドゲームは、オーバーです。それをラウンドゲームを反転し続けるための時間を持っていないプレイヤーのいずれかが、最初のプレイヤーがまだ非トランプトランプを配置するために継続する機会を持っている、とカードはデスクトップレベルに配置され、まだ既存の最初のケースでは、同じレベル、および総数はカードのデスクトップ・スタック上にないカードは手持ちのプレーヤーの総数は、カードを反転超えることはできません。その後、FLACのプレイヤーがこのラウンドを失い、そしてテーブルの上に自分の手をすべてのカードを追加します。ゲームの次のラウンド、最初のプレーヤーとFLACのプレイヤーのキャラクター変わりません。
後者の場合には、FLACのプレイヤーがこのラウンドを獲得します。次のラウンドとFLACのプレイヤーのキャラクターの上の手が交換可能になりながら、デスクトップ上のすべてのカードは、(ないデッキに)削除されますが、それは最初のプレーヤーFLACプレーヤーとなり、プレイヤーは最初のプレーヤーFLACなり。
手がデッキの全てを6かを持つことが起きるまで、ホイールとホイールの間に、手ではない半年以上の最後のラウンドの最初のプレイヤーは、彼が山の頂上からカードを開始する場合は、カードを取るために開始カードが削除されました。
試合が始まる前に、他のプレイヤーがまだ手である一方で、プレイヤーは、手札にカードを持っていない場合は、何のプレーヤーは、このボードゲームの手を獲得していません。2人の選手は何の手を持っていない場合は、協議会の試合は引き分けに終わりました。少なくとも二つのプレーヤーで手を持っていますが、最初のプレイヤーの手のみの切り札-彼は任意のアクションを行うことはできません-状況下で、我々は協議会FLACのプレイヤーがゲームに勝つと信じています。
タイガーとニンニクは、このようなゲーム、我々は両手と特別なカードのスーツの手に、デッキを与えているされている、あなたの目標は、はいラウンドこのゲームの最適戦略で勝者が誰であるかを決定することです。注意:両方のオープンのための甲板上の情報を。シベリアトラはトラの友人、ニンニクは、したがって、各ゲームタイガーアッパー手を聞かせすることを決めています。
タイガースは複雑すぎるゲームについて考えるので、タイガースは試合前に各ゲーム内のすべてのカードを起動するカードの特定の等級を削除しますが、作るために、少なくとも14枚のカードを持っているカードの少なくとも三つのレベル、残りのトラいることを保証するために、ゲームがスムーズに進みます。
解決 :
幸いなことに、この問題はほとんど不滅の観光疑問であるオリジナルタイトルで知られて見。
$ \ 95%の$のためのごみは、個人的にこの質問はほとんど価値があると思います。
限りがない2個のフリップフロッ王として、そして勝つために反転、または上の手を獲得。
最適な戦略のもと、FLACは上の手を持っている必要がありますだけでなく、その後、すべてうまく上甲板touchをしましょう。
トリックが問題です
#include <ビット/ STDC ++ H> 使用して名前空間STDを、const int型 N = 1005 ; ストリングS1、S2、S3、C、レベル。INT のmain(){ int型の T。CIN >> T; char型の CH; cinを>> CH; 一方、(T-- ){ int型 FLG = 0 。 getline(CIN、レベル)。 getline(CIN、S1)。 getline(CIN、S2)。用(int型 iは= 0 ; iが(< INT iが++;)s2.size(){}) であれば(S2 [i]が== ' R ' && S2 [I + 1 ] == ' J ' ) FLG ++ 。 もし(S2 [i]が== ' B ' && S2 [I + 1 ] == ' J ' ) FLG ++ 。 } のgetline(CIN、S3)。 getline(CIN、C)。 もし(FLG == 2 ) のprintf(" laohuの\ nを" ); 他 のprintf(" dasuanの\ nを" ); 。
問題Bスワップ
2つのn長$ $は$、B $を配置与えられ、各操作部は、$で$ A $ [のL、R] $うち、その最大値と最小スイッチングシーケンスであってもよいです。
操作で$ $ 345678、$ A $ $ B $となります。
$ 100個のデータの\ $%の保証、$ 1 \当量のn \の当量4096 $の場合
解決 :
同様の問題がある前に、まだ思考のクイックソートのソートセットをマージすることを検討してください。
私たちは、業務の$ S $の順序で$ A $配列を、並べ替えることができた場合は、$ bは$配列は、運用の$ T $のシーケンスである、ソートされます
それ以来、操作可逆ので、我々は唯一の出力を逆にする$ S $の正シーケンス出力、その後、$ T $が必要です。
マージソートを使用し、問題が順序を命じた2つの増分をマージする方法、に変換することができます。
この事は、我々が完了するまでに分割統治アプローチを使用する必要があります。
$ [L0、R0] $と$ [L1、R1] $をマージする現在の間隔を設定します。
、最小の長さの$ PT $を見つけるために、セグメント$ [L0、R0] $、$ [L1、R1] $マージするように設定されるように、$ [R0-PT + 1、R0]の数の大きさより$ $ [L1、L1 + PT-1] $サイズ多数。
今回は、$ [R0-PT + 1、L1 + PT-1]命じ$区間数が必要になりますので、我々は3つの$更新$操作を有効にする必要があります。
すなわち、区間$ [R0、PT + 1、R0] $、反転間隔$ [L1、L1 + PT-1] $、反転間隔$ [R0-PT + 1、L1 + PT-1]を反転$
この場合、2つのサブ問題に問題:$ [L0、L0-PT] $と$ [R0-PT + 1、R0] $組合せ; $ [L1、L1 + PT-1] $および$ [L1 + PT、R1]組み合わせました$。
そのようなパーティションは、それぞれ2つのセグメントに分割されてなり、時間複雑度は、$ $ Lは線路の長さを表し、$ O(log_2 1)$、です。
したがって、マージソートコートは、この問題の最終的な時間計算量は$ O(N {log_2} ^ 2 N)$です
# include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n,a[N]; vector< pair<int,int> >ans[2]; void update(int op,int l,int r) { for (int i=0;i<(r-l+1)/2;i++) { ans[op].push_back(make_pair(l+i,r-i)),swap(a[l+i],a[r-i]); } } void merge(int op,int l0,int r0,int l1,int r1) { if (l0>r0 || l1>r1) return; int l=min(r0-l0,r1-l1),pt=0; while (pt<=l) if (a[r0-pt]>=a[l1+pt]) pt++; else break; if (!pt) return; update(op,r0-pt+1,r0); update(op,l1,l1+pt-1); update(op,r0-pt+1,l1+pt-1); merge(op,l0,r0-pt,r0-pt+1,r0); merge(op,l1,l1+pt-1,l1+pt,r1); } void solve(int op,int l,int r) { if (l >= r) return; int mid = (l+r)>>1; solve(op,l,mid); solve(op,mid+1,r); merge(op,l,mid,mid+1,r); } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); solve(0,1,n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); solve(1,1,n); reverse(ans[1].begin(),ans[1].end()); printf("%d\n",ans[0].size()+ans[1].size()); for (int i=0;i<ans[0].size();i++) printf("%d %d\n",ans[0][i].first,ans[0][i].second); for (int i=0;i<ans[1].size();i++) printf("%d %d\n",ans[1][i].first,ans[1][i].second); return 0; }
Problem C actor
你有$m$种颜料,你要按照某个顺序选择颜料,每次在长度为$n$
的墙壁上刷一个区间,墙壁必须刷满,求可能刷出的墙壁方案数。
对于$100\%$的数据满足$1 \leq n\leq 10^6, m \leq 300$
Solution :
我们会首先考虑一个$O(mn^2)$的暴力$dp$.
设$f[i][j][k]$表示当前涂到第$i$个格子,使用了$j$个颜色,而有$k$个颜色一定会在后来的涂色中涂到。
那么$f[0][0][0] = 1$,采用刷表法转移。
考虑$f[i][j][k]$可以转移到
新放一个在之后将不会再刷到这个颜色: $f[i+1][j+1][k]$
新放一个在之后还会刷到这个颜色:$f[i+1][j+1][k+1]$
选择一个老颜色放在当前位置,并终结$f[i+1][j][k-1]$,此时要求$k\geq 1$
选择一个老颜色放在当前位置,并不终结$f[i+1][j][k]$, 此时要求$k\geq 1$
答案就是$\sum\limits_{i = 1}^{m} ({A_m}^i \times f[n][i][0])$
我们考虑到,最终的答案必然是由最多$2m$个相同颜色的块组成的,所以第一维状态可以压成和$m$有关系的了。
如果求出了块数为$i$的方案数$s$,那么可以通过插板法求出原来序列的答案了,即${C_{n-1}}^{i-1} \times s$
将状态改为$f[i][j][k]$表示当前考虑到$i$块,已经使用$j$个颜色,该块和该块之后最多能放置的已经放过的颜色的数目为$k$。
那么,$f[i+1][j][k] = f[i][j][k+1]+f[i][j][k+2] + ...$ ,此时只要在第$i+1$放一个已经放过的颜色就能实现。
若考虑新放置一个$j+1$的颜色,其有$(m-j)$种元素好挑,所以转移方程为$f[i+1][j+1][k+1] += f[i][j][k] \times (m-j)$
答案按照上述方法统计即可。
时间复杂度为$O(m^3)$
#include <stdio.h> typedef unsigned long long u64; const int N = 305, P = 1e9 + 7; int n, m, f[N << 1][N][N], c[N << 1], inv[N << 1], sum; void inc(int &x, int y){ (x += y) < P ?: x -= P; } void inc(int &x, u64 y){ x = (x + y) % P; } int main(){ // freopen("actor.in", "r", stdin); // freopen("actor.out", "w", stdout); int i, j, k, s; scanf("%d%d", &n, &m); f[1][1][1] = m, c[1] = inv[1] = 1; for (i = 2; i <= m << 1; ++i) { inv[i] = P - (u64)(P / i) * inv[P % i] % P; c[i] = (u64)c[i - 1] * inv[i - 1] % P * (n - i + 1) % P; } for (i = 1; i <= m << 1; ++i) { for (j = 1; j <= m; ++j) { for (k = j, s = 0; k >= 1; --k) { inc(f[i + 1][j][k], s); inc(f[i + 1][j + 1][k + 1], (u64)f[i][j][k] * (m - j)); inc(s, f[i][j][k]); } inc(sum, (u64)s * c[i]); } } printf("%d\n", sum); }