T1、デジタル
注\(S_I \)を示している\(1 \)する(Iは\)\順次接続されて得られた文字列を、
(T \(T \ ^ 10のLeq 4)\)\グループクエリ、各出力イネーブル\を(N- \(N当量10 ^ {\ 18})\) サブストリングに起こるよう\(s_x \)最小\(X \) 。
\(ソル\) :
吸盤のタイトル
唯一の3例:
1、\(N-X = \) ;
2、\(\ N-)の二つの部分の最初の部分に分割されている- \(1 \ X)サフィックス、後半\(X \)の接頭;
3、\は(\ N-)いくつかの部分に分割され、いくつかの完全に現れるがある(\ N-)\で。
彼は大きなシミュレーションを愛し、コードが読めないです。
読み取り可能なコードを参照してくださいここに。
時間複雑度\(O(T \ LOG_。3 ^ {N-10})\) 。
$出典:
#include <cstdio>
#include <algorithm>
int in() {
int x = 0; char c = getchar(); bool f = 0;
while (c < '0' || c > '9')
f |= c == '-', c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? -x : x;
}
long long lin() {
long long x = 0; char c = getchar(); bool f = 0;
while (c < '0' || c > '9')
f |= c == '-', c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }
long long n, Pow[105];
int nn;
//Devide into 3 parts begin
long long calc(const int len) {
int sub_len;
bool flag;
long long tmp, min = 1ll << 60ll;
for (int i = nn, j, k; i + len > nn && i - len >= 0; --i) {
long long now = n / Pow[nn - i] % Pow[len];
tmp = now;
flag = 0;
if (i != nn) {
++tmp;
sub_len = len + (tmp == Pow[len]);
if (!(n % Pow[nn - i] / Pow[nn - i - 1]) || tmp / Pow[sub_len - (nn - i)] != n % Pow[nn - i])
flag = 1;
}
if (flag == 1)
continue;
j = i, k = len;
while (now && j - k > 0) {
if (!(now / Pow[k - 1]) || now != n / Pow[nn - j] % Pow[k]) {
flag = 1;
break;
}
j -= k;
if (now == Pow[k - 1])
--k;
--now;
}
if (j) {
if (n / Pow[nn - j] != now % Pow[j])
flag = 1;
}
if (!flag) {
chk_min(min, tmp);
}
}
return min;
}
//Devide into 3 parts end
int main() {
//freopen("in", "r", stdin);
freopen("number.in", "r", stdin);
freopen("number.out", "w", stdout);
int T = in();
long long res;
Pow[0] = 1;
for (int i = 1; i <= 17; ++i)
Pow[i] = Pow[i - 1] * 10;
while (T--) {
long long tmp;
n = res = tmp = lin(), nn = 0;
while (tmp)
tmp /= 10, ++nn;
tmp = n;
//Devide into 2 parts begin
for (int i = 1; i < nn; ++i) {
if (n % Pow[nn - i] / Pow[nn - i - 1]) {
for (int j = std::max(i, nn - i); j < nn; ++j) {
if (n % Pow[nn - j] == (n / Pow[nn - i] + 1) % Pow[i] / Pow[i - (nn - j)]) {
chk_min(res, (n / Pow[nn - i] + 1) % Pow[i] + n % Pow[nn - i] / Pow[nn - j] * Pow[i]);
}
}
chk_min(res, (n / Pow[nn - i] + 1) % Pow[i] + n % Pow[nn - i] * Pow[i]);
}
}
//Devide into 2 parts end
for (int i = 1; tmp; ++i, tmp /= 10) {
chk_min(res, calc(i));
}
printf("%lld\n", res);
}
return 0;
}
T2月
所与\(n回のM \(\ nは、m個の\当量100)\) 4ユニコム到着メッシュ\を((I、J)\ ) を得ることができる\(C_ {I、J} \(0 \ 当量C_ {I、J} \当量10 ^ 9)\) を繰り返しスコア(取得)
するための所定の出発点\((B)\ (1 \が\の当量のN、1 \当量Bの\の当量の当量メートル)\) 、ちょうど取る見つける(k個の\(k個の\当量10 ^ 9)\ \) バック最大スコアの先頭にステップの後。
確保\(2 | K \)、\ (C_ {I、J} = 0 \) 。
\(ソル\) :
以降\(k個の\)が、大きい場合、最適解は、サイクルの期間を通して経路を歩いた後に繰り返す必要があり
、パスは、2つの隣接する格子を繰り返さなければならないことを証明することができる
\(PRF \) :
繰り返し経路の任意の期間について、あなたは平均スコアを見つけることができます2つの重複格子パス段落全体の平均よりも小さくありません。
\(QED \)
注\(F_ {I、X、 Y} \)は、 ダウン表す\(Iは\)ステップ到着\((x、y)を\ ) の最大値であり、次いで、4つの格子とのリンクが最も高いダウンスコア$を選択\ FRAC {K - 2I} { 2} $ サイクル;
\(Iは\)まで(\ \分\ {NM、\ K FRAC {2} {} \} \)。
時間複雑度\(O(N-M ^ 2 ^ 2)\) 。
\(出典\) :
#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
int x = 0; char c = getchar(); bool f = 0;
while (c < '0' || c > '9')
f |= c == '-', c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }
const int N = 105;
int n, m, A, B, k;
int mp[N][N];
long long f[2][N][N], res;
void work() {
int cur = 0, lim = std::min(n * m, k >> 1);
memset(f[0], -1, sizeof(f[0]));
f[0][A][B] = 0;
for (int i = 0; i < lim; ++i, cur ^= 1) {
memset(f[cur ^ 1], -1, sizeof(f[cur ^ 1]));
for (int x = 1; x <= n; ++x) {
for (int y = 1; y <= m; ++y) {
if (!~f[cur][x][y])
continue;
if (i + i < k) {
int max = -1;
chk_max(max, mp[x + 1][y]);
chk_max(max, mp[x - 1][y]);
chk_max(max, mp[x][y + 1]);
chk_max(max, mp[x][y - 1]);
chk_max(res, f[cur][x][y] + f[cur][x][y] - mp[x][y] + 1ll * (k - i - i) / 2 * (mp[x][y] + max));
}
if (x < n)
chk_max(f[cur ^ 1][x + 1][y], f[cur][x][y] + mp[x + 1][y]);
if (x)
chk_max(f[cur ^ 1][x - 1][y], f[cur][x][y] + mp[x - 1][y]);
if (y < m)
chk_max(f[cur ^ 1][x][y + 1], f[cur][x][y] + mp[x][y + 1]);
if (y)
chk_max(f[cur ^ 1][x][y - 1], f[cur][x][y] + mp[x][y - 1]);
}
}
}
if (lim + lim <= k) {
for (int x = 1; x <= n; ++x)
for (int y = 1; y <= m; ++y)
if (~f[cur][x][y])
chk_max(res, f[cur][x][y] + f[cur][x][y] - mp[x][y]);
}
printf("%lld\n", res);
}
int main() {
//freopen("in", "r", stdin);
freopen("maja.in", "r", stdin);
freopen("maja.out", "w", stdout);
n = in(), m = in(), A = in(), B = in(), k = in();
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
mp[i][j] = in();
work();
return 0;
}
T3、友人のdjq円
\(N \(N \の当量 42)\) 個体、番号\(1 \) 〜\(N- \) 、点の間の関係\(0 \)二種類、公知\(m個\)グループとの関係(二人の関係は不思議、)を2回与えるものではありません\(1 \)他の人との関係を、
人の数があるとし\(X-が\) ;
場合は\(1 \) 、彼との関係が知られていますその後、両者の関係は変化しない(関係は双方向である)、
そうでなければ\(1 \)特定の順序リストされている人に、彼の関係が知られている、
第一と仮定\(1 \)および\(X \)を認識しながら人々は、\(y軸の\) 、そう\(1 \)と\(X \)の関係がされて()、\ XOR \(X、Y)\ Y-(1)\、\((X軸、Y軸)\)を表す\(X、Yの\)との関係を、
新たに設立された関係は、他の人の関係の決意には影響しません。
個別ものを探していると、\(1 \)の関係は、このようなヒト配列を、知られているもの(1 \)\関係\(0 \)最大数、出力の数。
\(ソル\) :
で開始します(1 \)\関係\(0 \)に設定されている(Aを\)\、および\(1 \)知らないが、(A \)\の人々を知っている何人かの人々へ\(Bの\) 、明らかに他の人が考えていません。
場合は\(| A | \のLeq 20 \) 、あなたがすることができます\(A \)の圧力などが、覚えている(のf_i \)\を表し\(私は\)リスト最適解にこれらの人々の浮上している、次の列挙人々が発生する可能性があります。
それ以外の場合は、\(B \)圧力、覚えているような\(のf_iは、\)を表す\(私は\)これらの人々のは、上記の転送最適解との関係を決定しました。
時間複雑度\(O(2 ^ {\ FRAC {{N-2}}} ^ N-2)\)。
\(出典\) :
#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
int x = 0; char c = getchar(); bool f = 0;
while (c < '0' || c > '9')
f |= c == '-', c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }
const int N = 51;
int n, m, cnt_a, cnt_b, tot_st, t[N][N], mp[N], id[N], f[1 << 21 | 1];
long long fri[N], agn[N];
int bit_cnt(long long x, int ret = 0) {
for (; x; x &= (x - 1), ++ret);
return ret;
}
namespace A {
void work() {
tot_st = (1 << cnt_a) - 1;
for (int i = 2; i <= n; ++i)
if (~t[1][i])
id[mp[i]] = i;
for (int i = 0; i < tot_st; ++i) {
long long now = 0;
for (int j = 1; j <= cnt_a; ++j)
if (i & (1 << (j - 1)))
now |= (fri[id[j]] | agn[id[j]]);
for (int j = 1; j <= cnt_a; ++j)
if (~i & (1 << (j - 1))) {
if (!t[1][id[j]]) {
chk_max(f[i | (1 << (j - 1))], f[i] + bit_cnt(~now & fri[id[j]]));
} else {
chk_max(f[i | (1 << (j - 1))], f[i] + bit_cnt(~now & agn[id[j]]));
}
}
}
for (int i = 1; i <= cnt_a; ++i)
f[tot_st] += (t[1][id[i]] == 0);
printf("%d\n", f[tot_st]);
}
}
namespace B {
void work() {
tot_st = (1 << cnt_b) - 1;
for (int i = 2; i <= n; ++i)
if (~t[1][i])
id[mp[i]] = i;
for (int i = 0; i < tot_st; ++i) {
for (int j = 1; j <= cnt_a; ++j)
if (~i & (fri[id[j]] | agn[id[j]])) {
if (!t[1][id[j]]) {
chk_max(f[i | fri[id[j]] | agn[id[j]]], f[i] + bit_cnt(~i & fri[id[j]]));
} else {
chk_max(f[i | fri[id[j]] | agn[id[j]]], f[i] + bit_cnt(~i & agn[id[j]]));
}
}
}
for (int i = 1; i <= cnt_a; ++i)
f[tot_st] += (t[1][id[i]] == 0);
printf("%d\n", f[tot_st]);
}
}
int main() {
//freopen("in", "r", stdin);
freopen("friends.in", "r", stdin);
freopen("friends.out", "w", stdout);
n = in(), m = in();
memset(t, -1, sizeof(t));
for (int i = 1, x, y; i <= m; ++i) {
x = in(), y = in();
t[x][y] = t[y][x] = in();
}
for (int i = 2; i <= n; ++i) {
if (!~t[1][i])
continue;
mp[i] = ++cnt_a;
for (int j = 2; j <= n; ++j) {
if (!~t[1][j] && ~t[i][j]) {
if (!mp[j])
mp[j] = ++cnt_b;
if (!t[i][j])
fri[i] |= (1ll << (mp[j] - 1));
else
agn[i] |= (1ll << (mp[j] - 1));
}
}
}
if (cnt_a <= 20) {
A::work();
} else {
B::work();
}
return 0;
}