NOIPシミュレーション演習6
- 300のうち、I 110。260改正後。
- ミディアム困難。
ギャンブラー
説明
それぞれが自分のチップを持っているNギャンブラーの手があります。ギャンブルでは、彼らは周りのギャンブラーからお金を借りるので、彼らすることができます
チップは負であってもよいが、チップは必ずしも整数です。ときギャンブル、Nチップ間のギャンブラーだけで、別の3
勝者であるチップギャンブラーの合計。複数の資格ギャンブラー場合は、最大の人工チップの勝者を選択します。
5ギャンブラ例えば、各ギャンブル2,3,5,7,12の終わりに、彼らはそれ以来12 = 2 + 3 + 7は、ホルダ12の勝者です。
入力
最初の整数を行うn個(1 <= N <= 1000)Nとすると、ギャンブラを表します。次のn行
整数x(8 ^ 10 <= X <= 10 ^ 8)は各ギャンブラの手に賭けるチップの終了を示します。
出力
唯一の勝者の手の中にチップのギャンブルの整数の終わりに。何の勝者が存在しない場合、出力は「なし
溶液"。
サンプル入力
5
2
3
5
7
12
サンプル出力
12
ソリューション:
- 暴力列挙。
- emmm ... ..ゼロの私の質問バースト。
- 、DPの読み書き、読み始めて、すぐにレコードの検索になって、間違っていました。自信を持って、爆発の結果を支払います。その理由は、境界状況が考慮されていないがあるということです。
- 3つの正ソリューション再循環+剪定です。衝撃を受けました。
- 具体的には、最初の注文です。最初の勝者は、第2の再列挙によって1つのこんにゃく、ユーザ2のコンニャクお金第再列挙のお金、お金列挙を再度、それらコンニャクお金3を列挙する必要がないので列挙によってフロント若者は、4×のためのお金を数え仮定して、計算しました。xが間違いであれば、爆発樽は、アレイ内のスペースを宣告しました。あまり直接バイナリサーチ聖歌。
書かれている複雑さはO(n ^ 3)、私はしませんでした。ポイントにそれを剪定!あなたはお金1 * 3 <お金の勝者を持っている現在のこんにゃくを想定し、1でお金こんにゃくを列挙するとき。あまり直接ブレーク。理由は非常に単純ですが、ほとんどの人はありません三回のこんにゃくは、その後、どのようにアップポートフォリオの残りの部分は取得することができますか?
- 概要:小さな検索データをもと考えることができます。しかし、このような、唯一の3つのこのようなデータは極めて小さな。+剪定は暴力的とみなすことができます。
いずれかの問題は非常に難しい取得する必要はありません。
#include <iostream>
#include <cstdio>
#include <algorithm>
#define N 1005
using namespace std;
int n;
int a[N];
int find(int x)
{
int pos = lower_bound(a + 1, a + 1 + n, x) - a;
return a[pos];
}
int main()
{
cin >> n;
if(n < 4) {cout << "no solution"; return 0;}
for(int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + 1 + n);
for(int i = n; i >= 4; i--)
for(int j = i - 1; j >= 1; j--)
{
if(a[j] * 3 < a[i]) break;
for(int k = j - 1; k >= 1; k--)
{
if(a[k] * 2 + a[j] < a[i]) break;
int v1 = a[i], v2 = a[j], v3 = a[k], v4 = v1 - v2 - v3;
if(find(v4) == v4) {cout << v1; return 0;}
}
}
cout << "no solution";
return 0;
}
サルはバナナを食べます
説明
サルのIQを研究している一部の研究者は、彼らが天井からぶら下がってバナナの束であり、いくつかの箱を提供します
猿は非常にスマートであるならば、私はこれまでバナナを持ってまで子供が、それは、一緒にこれらのボックスをオーバーレイします。完全に研究者
ボックスのn種類を提供するが、各ボックスの数に限定されるものではありません。各ボックスには、(xi、yi、zi)との寸法を有する矩形です。
底面の要件上記箱に入れボックスを重ねたときの長さよりも小さく、幅がボックスの底部に配置する必要があります
上面の長さと幅。(ボックスは、一つ一つが重畳します)
ボックスのいくつかの大きさを考えると、彼らは一緒に加え、最大の高さを取得するようにプログラムすることができます。
入力
(1 <= N最初の行は、N- <= 30)、いくつかのボックスを示しています。
3つの数字のXI、YI、ZIの次のn行、それぞれ、ボックスのサイズ。
1 <= XI、李、ZIと <= 104。
出力
- それらは一緒に添加することができる最大の高さを表す数だけ。
サンプル入力
2
6 8 10
5 5 5
サンプル出力
21
ソリューション:
- DP。
ダイレクトアウト。しかし、単に実際に<= 30怖がっ疑問データの範囲を確認するために、開梱、それは圧力のようだと思いました。慎重な思考の結果は、実際には、本質的には、その後すぐにカットオフ「ミサイルインターセプト」です。(データ範囲が小さすぎるため、この問題もを検索することができます... ...
そのためボックスの何度もすることができますので、ボックスは、実際に「6」のボックスです。仮定X、Y、Z。高いXを行うための2種類があり、yが高いの2種類を行うと、zは高の2種類、6種類の合計を行う必要があります。N * 6は、ボックス種アレイに添加しました。LISのこの配列は再びそれを行うことができます。しかし、そのメンテナンスが最大、最長のないアップ/ダウンシーケンスであることに注意。
#include <iostream>
#include <cstdio>
#include <algorithm>
#define N 5005
using namespace std;
struct A {int x, y, z;} a[N];
int n, ans, cnt;
int dp[N];
bool cmp(A u, A v)
{
if(u.x == v.x)
{
if(u.y == v.y) return u.z > v.z;
else return u.y > v.y;
}
else return u.x > v.x;
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
int x, y, z;
cin >> x >> y >> z;
a[++cnt].x = x, a[cnt].y = y, a[cnt].z = z;
a[++cnt].x = y, a[cnt].y = x, a[cnt].z = z;
a[++cnt].x = y, a[cnt].y = z, a[cnt].z = x;
a[++cnt].x = z, a[cnt].y = y, a[cnt].z = x;
a[++cnt].x = z, a[cnt].y = x, a[cnt].z = y;
a[++cnt].x = x, a[cnt].y = z, a[cnt].z = y;
}
n *= 6;
sort(a + 1, a + 1 + n, cmp);
for(int i = 1; i <= n; i++) dp[i] = a[i].z;
for(int i = 2; i <= n; i++)
for(int j = 1; j < i; j++)
if(a[j].x > a[i].x && a[j].y > a[i].y)
dp[i] = max(dp[i], dp[j] + a[i].z);
for(int i = 1; i <= n; i++) ans = max(ans, dp[i]);
cout << ans;
return 0;
}
ネックレス工場
トピック:
- 写真はありますが、転送リンク
ソリューション:
- バランスのとれたツリー/ツリーライン
- 私はGUGU区を取得しようとしました。この問題は肯定的解決策、
将来的に記入します。 - 暴力の最初の戦いは、実際にはRは、操作が間違っていた非常に残念をずらし以来初めてでした。
- 暴力問題のこのアイデアは非常に単純ではなく、細部の多くのです!
#include <iostream>
#include <cstdio>
#include <cstring>
#define N 500005
using namespace std;
int n, c, q;
int a[N], b[N];
bool vis[N];
int read()
{
int x = 0; char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return x;
}
void step1()
{
int k = read() % n;
for(int i = 1; i <= n; i++)
{
int j = (i + k) % n;
if(!j) j = n;
b[j] = a[i];
}
for(int i = 1; i <= n; i++) a[i] = b[i];
}
void step2()
{
for(int i = 2; i <= (n + 1) / 2; i++)
swap(a[i], a[n - i + 2]);
}
void step3()
{
int u = read(), v = read();
swap(a[u], a[v]);
}
int getCnt(int u, int v)
{
int pos = u, cnt = 0;
while(pos != v)
{
cnt++, pos++;
if(pos == n + 1) pos = 1;
}
return cnt;
}
void step4()
{
int u = read(), v = read(), w = read();
int pos = u, cnt = 1 + getCnt(u, v);
for(int i = 1; i <= cnt; i++)
{
a[pos] = w;
pos++;
if(pos == n + 1) pos = 1;
}
}
void step5()
{
int ans = 0, pos;
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++)
if(!vis[i])
{
ans++, vis[i] = 1;
pos = i;
while(1)
{
pos++;
if(pos == n + 1) pos = 1;
if(vis[pos]) break;
if(a[pos] == a[i]) vis[pos] = 1;
else break;
}
pos = i;
while(1)
{
pos--;
if(!pos) pos = n;
if(vis[pos]) break;
if(a[pos] == a[i]) vis[pos] = 1;
else break;
}
}
printf("%d\n", ans);
}
void step6()
{
int l = read(), r = read();
int ans = 0, u = l, v = -1, cnt = 1 + getCnt(l, r);
for(int i = 1; i < cnt; i++)
{
v = (u + 1) % n;
if(!v) v = n;
if(a[u] != a[v]) ans++;
u++;
if(u == n + 1) u = 1;
}
printf("%d\n", ans + 1);
}
int main()
{
cin >> n >> c;
for(int i = 1; i <= n; i++) a[i] = read();
cin >> q;
for(int i = 1; i <= q; i++)
{
char c[4]; scanf("%s", c);
if(c[0] == 'R') step1();
else if(c[0] == 'F') step2();
else if(c[0] == 'S') step3();
else if(c[0] == 'P') step4();
else if(c[0] == 'C' && c[1] == 'S') step6();
else if(c[0] == 'C') step5();
}
return 0;
}