2019頭の牛とより多くの乗客第十の学校のフィールド
A.ブラックジャック
upsolved
表題の問い合わせはしていると等価である\(N- \)番目の値と題する(X_I \)\記事のランダム配列である、提供\(POS \)最初の重量は接頭辞よりも大きい場合である\(A \) 、位置シーク\(\和の\ limits_を{I = 1} ^ {POS} X_I <= B \) 確率
\((1 <= N <= 500、1 <= A <B <= 500、\和X_I> B)\)
\(O(N)\)よりも大きいような接頭語の重みの列挙\(\)に設けられ、物品の、\(DP [I] [J ] [k]は\) にかかわらず、現在の列挙された項目を表す\(P \) 、前者\(Iは\)物品番目使用\(J \)を重み目とする)(K \を\はプログラムの数であり、十分に満たしている\(N =、0 < = J <N、MAX(0、 -x_p + 1)<= K <=分(B-x_p)\) 値DPの応答への寄与は移動され
なお、このとき、\(DP \)値は、あなたが配置を計算したいだけの組み合わせを計算し、番号方式が上に乗るだろう
\(J!*(NJ-1)!\)
あなたがするたびに列挙バックパックを再計算している場合は、複雑さがある\(O(N ^ 4) \) 、あなたが最初に、リュックサックを検討バックパックは、すべての項目が含まれて計算し、各列挙で、現在のアイテムを撤回する引退することができ、計算が時間複雑度までに何度も低下、\(O(N ^ 3)\) 、空間的複雑さは、スクロール・アレイを使用するように最適化することができる\(O(N ^ 2) \)
6つの質問は時間がない時に行われ、この問題はまだ出て行うのに十分な時間でなければなりません場合は...
#include <bits/stdc++.h>
using namespace std;
const int N = 510;
double dp[2][N][N], p[N], ans;
int n, a, b, x[N];
int main() {
scanf("%d%d%d", &n, &a, &b);
dp[0][0][0] = 1;
for(int i = 1; i <= n; ++i) {
scanf("%d", &x[i]);
memcpy(dp[i & 1], dp[(i & 1) ^ 1], sizeof(dp[0]));
for(int j = 1; j <= n; ++j)
for(int k = x[i]; k <= b; ++k)
dp[i & 1][j][k] += dp[(i & 1) ^ 1][j - 1][k - x[i]];
}
p[1] = 1.0 / n;
for(int i = 2; i <= n; ++i)
p[i] = p[i - 1] * (i - 1) / (n - i + 1);
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= n; ++j)
for(int k = x[i]; k <= b; ++k)
dp[n & 1][j][k] -= dp[n & 1][j - 1][k - x[i]];
for(int j = 0; j < n; ++j) {
for(int k = max(0, a - x[i] + 1); k <= a && k + x[i] <= b; ++k)
ans += dp[n & 1][j][k] * p[j + 1];
}
for(int j = n; j >= 1; --j) {
for(int k = b; k >= x[i]; --k)
dp[n & 1][j][k] += dp[n & 1][j - 1][k - x[i]];
}
}
printf("%.15f\n", ans);
return 0;
}
B.コーヒーチキン
午前0時13分(+1)で解か
フィボナッチ数は配列フィボナッチように、そのような文字列を考える[1] \(S = "コーヒー"、Sを[2] = "チキン"、S [I] =のS [I - 2] + S [I - 1】(I> 2)\ )
たびに\(N、K(1 < = N <= 500、1 <= K <= 1E12)\)
必要な出力\(N- \)文字列の\(K \)に目\(K + 9 \)文字(無出力しません)
前処理\(500 \)再帰的プロセス等により爆発する各ストリング(長い長い\)\であってもよいが(1E12 + 9 \)\分を取ります
#include <bits/stdc++.h>
using namespace std;
const long long MAX = 1e12 + 9;
long long f[510], k;
int T, n;
char s1[] = "COFFEE", s2[] = "CHICKEN";
void get(int x, long long num) {
if(x == 1) cout << s1[num - 1];
if(x == 2) cout << s2[num - 1];
if(x <= 2) return;
if(f[x - 2] >= num) get(x - 2, num);
else get(x - 1, num - f[x - 2]);
}
int main() {
f[1] = 6, f[2] = 7;
for(int i = 3; i <= 500; ++i)
f[i] = min(MAX, f[i - 1] + f[i - 2]);
cin >> T;
while(T--) {
cin >> n >> k;
for(long long i = k; i < k + 10 && i <= f[n]; ++i)
get(n, i);
cout << endl;
}
return 0;
}
D.韓信と彼の軍隊
1時20(+1)で解か
ハン兵士の問題は、アップ\(100 \)は、合同式は、プライムモジュラスを保証しない、決定劣らない又は全く溶液\(m個\)ソリューション溶液または最小出力、デジタルレンジ1E5
私はその後、WAをexcrtをコピーし、それは、Java、長い時間のための括弧曲に間違った位置の結果を使用するように書き換えられ、int型バーストかもしれません実現しました...
import java.io.*;
import java.util.*;
import java.math.*;
public class Main {
static int n;
static BigInteger m;
static BigInteger[] a = new BigInteger[110], r = new BigInteger[110];
static BigInteger[] exgcd(BigInteger a, BigInteger b) {
BigInteger[] res = new BigInteger[3];
if(b.equals(BigInteger.ZERO)) {
res[0] = a;
res[1] = BigInteger.ONE;
res[2] = BigInteger.ZERO;
return res;
}
BigInteger[] tmp = exgcd(b, a.mod(b));
res[0] = tmp[0];
res[1] = tmp[2];
res[2] = tmp[1].subtract(a.divide(b).multiply(tmp[2]));
return res;
}
static BigInteger excrt() {
BigInteger M = a[1], R = r[1], x, y, d;
for(int i = 2; i <= n; ++i) {
BigInteger[] rrr = exgcd(M, a[i]);
d = rrr[0]; x = rrr[1]; y = rrr[2];
if(!(R.subtract(r[i]).mod(d)).equals(BigInteger.ZERO)) return BigInteger.valueOf(-1);
x = (R.subtract(r[i]).divide(d).multiply(x)).mod(a[i]);
R = R.subtract(M.multiply(x));
M = M.divide(d).multiply(a[i]);
R = R.mod(M);
}
return R.mod(M).add(M).mod(M);
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
n = cin.nextInt();
m = cin.nextBigInteger();
for(int i = 1; i <= n; ++i) {
a[i] = cin.nextBigInteger();
r[i] = cin.nextBigInteger();
}
BigInteger res = excrt();
if(res.equals(BigInteger.valueOf(-1))) {
System.out.println("he was definitely lying");
}
else if(res.compareTo(m) > 0) {
System.out.println("he was probably lying");
}
else {
System.out.println(res);
}
}
}
E.ヒルベルトソート
午前1時54分で解きます
行うには彼のチームメイト
F.ポッピングバルーン
3:51(+1)で解か
二次元平面のある\(N- \)点は、次の水平3と3つの垂直線を選択しなければならない、との間の距離の水平(垂直)が一定値に隣接する\(R&LTの\)ラインを通過しようとしています、点の最大数\((1 <= N、 R <= 1E5、0 <= xと、Y <= 1E5)\)
どうやら垂直線上の点の上に計算された第1の時間を捨てると、次のように戻すために、セグメントツリーのメンテナンスポイントを横軸、列挙の縦線を垂直方向重みを列挙唯一の水平線垂直線を考えてみましょう、3は同じ、限りポイントの寄与を生成することができなかったような行の位置
PS:あなたは直接の重みセグメントツリーの多重集合を記述することはできません
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int lim = 1e5 + 1;
int mx[N << 2], n, r, x, y;
void update(int rt, int l, int r, int pos, int val) {
if(l == r) {
mx[rt] += val;
return;
}
int mid = l + r >> 1;
if(pos <= mid)
update(rt << 1, l, mid, pos, val);
else
update(rt << 1 | 1, mid + 1, r, pos, val);
mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]);
}
vector<int> c[N];
int main() {
scanf("%d%d", &n, &r);
for(int i = 1; i <= n; ++i) {
scanf("%d%d", &x, &y);
x++, y++;
c[y].push_back(x);
if(y - r >= 1)
c[y - r].push_back(x);
if(y + r <= lim)
c[y + r].push_back(x);
update(1, 1, lim, x, 1);
if(x - r >= 1)
update(1, 1, lim, x - r, 1);
if(x + r <= lim)
update(1, 1, lim, x + r, 1);
}
int ans = 0;
for(int y = 1; y <= lim; ++y) {
for(auto i: c[y]) {
update(1, 1, lim, i, -1);
if(i - r >= 1)
update(1, 1, lim, i - r, -1);
if(i + r <= lim)
update(1, 1, lim, i + r, -1);
}
ans = max(ans, (int)c[y].size() + mx[1]);
for(auto i: c[y]) {
update(1, 1, lim, i, 1);
if(i - r >= 1)
update(1, 1, lim, i - r, 1);
if(i + r <= lim)
update(1, 1, lim, i + r, 1);
}
}
printf("%d\n", ans);
return 0;
}
H.どもり化学者
午前0時25分で解きます
図ヘキサンはあなたヘキサン決定された表現を、与えるために
以下のような見た目の学位...
J.木材加工
3:25(+2)において解きます
\(N- \)ブロック厚板\(K \)ブロック(ボードはすべてに参加しなければならない)、横方向スプライス方法は、一緒に固執スプライシングに関与する厚板の高さ未満に等しい縦方向の最小値を選択し、すべてこれは非常に厚板に切断し、廃棄し、木材を回転することができない再利用しない、最小のカット部分は、プログラムの数必要な部分をカット\((1 <= N < = 5000、1 <= K <= 3000 )\)
まず、高さによってソートボードは、明らかに最後の\(K \)木片をしなければならない(K \)\連続した区間を
セット\(DP [I] [jが 】\) 前者表す\(Iは\)ブロック厚板を\(J \)廃棄物のブロックの最小値、\(DP [I] [J ] = \分\ limits_ { K = 0} ^ {I- 1}(DP [K] [J - 1] +和[I] -和[K] - (sumw [I] - sumw [K])* H [K + 1]) \)
この複雑さは、直接転写事である(N ^ 2K)(O \ \) が、勾配を最適化することができる\(O(NK)\)
(また、四角形不平等の最適化を使用することができます)
そのためしばらく時間ブレースの位置間違った口調で...
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const int N = 5010;
struct B {
int w, h;
bool operator<(const B &rhs) const {
return h < rhs.h;
}
}a[N];
int n, K;
long long dp[N][2010], sum[N], sw[N];
int que[N], head, tail;
inline LL Y(int t, int x) {return dp[x][t - 1] + sw[x] * a[x + 1].h - sum[x];}
inline LL KY(int t, int i, int j) {return Y(t, i) - Y(t, j);}
inline LL X(int x) {return a[x + 1].h;}
inline LL KX(int i, int j) {return X(i) - X(j);}
int main() {
scanf("%d%d", &n, &K);
for(int i = 1; i <= n; ++i)
scanf("%d%d", &a[i].w, &a[i].h);
sort(a + 1, a + n + 1);
a[n + 1].h = a[n + 1].w = 1e7;
for(int i = 1; i <= n; ++i) {
sum[i] = sum[i - 1] + 1LL * a[i].h * a[i].w;
sw[i] = sw[i - 1] + a[i].w;
}
memset(dp, 0x3f, sizeof(dp));
for(int i = 1; i <= n; ++i)
dp[i][1] = sum[i] - a[1].h * sw[i];
for(int k = 2; k <= K; ++k) {
head = tail = 0;
dp[k][k] = 0;
que[tail++] = k - 1;
for(int i = k; i <= n; ++i) {
while(head < tail - 1 && (__int128)KY(k, que[head + 1], que[head]) <= (__int128)sw[i] * KX(que[head + 1], que[head])) head++;
int j = que[head];
dp[i][k] = dp[j][k - 1] + sum[i] - sum[j] - (sw[i] - sw[j]) * a[j + 1].h;
while(head < tail - 1 && (__int128)KY(k, que[tail - 1], que[tail - 2]) * KX(i, que[tail - 1]) >= (__int128)KY(k, i, que[tail - 1]) * KX(que[tail - 1], que[tail - 2])) tail--;
que[tail++] = i;
}
}
printf("%lld\n", dp[n][K]);
return 0;
}
多くの学校が終わった2019頭の牛オフ、しかし、問題は、アップ完了していません