DRD要在一个编辑器里打出N个字符并保存
对于某一时刻,有两种操作:
问最优策略下,完成任务的用时期望是多少
DP,f[i]表示打出前i个字符并保存所需用时的期望
转移方程为f[i] = min{f[j] + g[i-j] + x}
其中g[i]表示连续打出i个字符不出错的用时期望
可以得到递推式g[i] = (g[i-1] + 1) * (1 - p) + (g[i-1] + 1 + g[i]) * p
整理得g[i] = (g[i-1] + 1) / (1 - p)
不难发现,g的增长速率非常快,故转移时只需考察前面很少的状态
/**
* Copyright (c) 2015 Authors. All rights reserved.
*
* FileName: A.cpp
* Author: Beiyu Li
* Date: 2015-05-25
*/
#include
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = 100000 + 5;
int n, x;
double p, f[maxn];
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
scanf("%d%lf%d", &n, &p, &x);
p = 1 - p;
f[0] = 0;
For(i,1,n) {
double g = 1 / p;
f[i] = f[i-1] + g + x;
for (int j = i - 2; j >= 0; --j) {
g = (g + 1) / p;
if (g > f[i]) break;
f[i] = min(f[i], f[j] + g + x);
}
}
printf("Case #%d: %.10f\n", ++cas, f[n]);
}
return 0;
}
输入一个整数k和一个字符串,输出该字符串使用Base64编码k次后的结果
模拟,使用bitset可以很方便的实现字符与01串的相互转换
/**
* Copyright (c) 2015 Authors. All rights reserved.
*
* FileName: B.cpp
* Author: Beiyu Li
* Date: 2015-05-25
*/
#include
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = 100000 + 5;
int k;
char s[maxn];
char mp[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void trans()
{
string bit;
int n = strlen(s);
rep(i,n) bit += bitset<8>(s[i]).to_string();
while (bit.length() % 6) bit += '0';
n = 0;
for (int i = 0; i < bit.length(); i += 6)
s[n++] = mp[bitset<6>(bit.substr(i, 6)).to_ulong()];
while (n % 4) s[n++] = '=';
s[n] = 0;
}
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
scanf("%d%s", &k, s);
while (k--) trans();
printf("Case #%d: %s\n", ++cas, s);
}
return 0;
}
给出一个长度为N,只包含加、乘、乘方的运算序列
*4, +2, ^3, +8, *6
要求支持两种操作:
对29393分解质因数得29393 = 7 * 13 * 17 * 19
具体的线段树维护方式,请参照下面的代码
/**
* Copyright (c) 2015 Authors. All rights reserved.
*
* FileName: C.cpp
* Author: Beiyu Li
* Date: 2015-05-25
*/
#include
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = 50000 + 5;
const int mod[] = {7, 13, 17, 19};
int n, m;
char p[maxn];
int v[maxn], r[4];
int f[1<<18][4][20];
int pow_mod(int a, int b, int m)
{
int res = 1;
for (; b; a = a * a % m, b >>= 1) if (b & 1) res = res * a % m;
return res;
}
void gcd(LL a, LL b, LL &g, LL &x0, LL &y0)
{
if (!b) g = a, x0 = 1, y0 = 0;
else gcd(b, a % b, g, y0, x0), y0 -= x0 * (a / b);
}
int china(int r[], const int m[], int n)
{
LL r0 = r[0], m0 = m[0];
for (int i = 1; i < n; ++i) {
LL r1 = r[i], m1 = m[i], g, x0, y0;
gcd(m0, m1, g, x0, y0);
if ((r1 - r0) % g) return -1;
LL r2 = (r1 - r0) / g * x0 % m1, m2 = m0;
m0 = m0 / g * m1;
r0 = (r0 + r2 * m2 % m0) % m0;
}
return (r0 + m0) % m0;
}
void update(int o, int l, int r, int i)
{
if (l == r) {
rep(i,4) rep(j,mod[i]) {
if (p[l] == '+') f[o][i][j] = (j + v[l]) % mod[i];
if (p[l] == '*') f[o][i][j] = (j * v[l]) % mod[i];
if (p[l] == '^') f[o][i][j] = pow_mod(j, v[l], mod[i]);
}
return;
}
int mid = (l + r) >> 1, lc = o * 2, rc = o * 2 + 1;
if (i == -1 || i <= mid) update(lc, l, mid, i);
if (i == -1 || i > mid) update(rc, mid + 1, r, i);
rep(i,4) rep(j,mod[i]) f[o][i][j] = f[rc][i][f[lc][i][j]];
}
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
scanf("%d%d\n", &n, &m);
For(i,1,n) p[i] = getchar(), scanf("%d\n", &v[i]);
update(1, 1, n, -1);
printf("Case #%d:\n", ++cas);
while (m--) {
int op, x, i;
scanf("%d", &op);
if (op == 1) {
scanf("%d", &x);
rep(i,4) r[i] = f[1][i][x%mod[i]];
printf("%d\n", china(r, mod, 4));
} else {
scanf("%d ", &i);
p[i] = getchar(), scanf("%d", &v[i]);
update(1, 1, n, i);
}
}
}
return 0;
}
给出一个长度为N的数列,以及M个查询,初始答案为0
对于每个查询
p=9223372034707292160=231×3×5×17×257×65536
单独考虑p的每个质因子q,都是 2k+1 形式的素数,而数列中的数又是 x2y 的形式
因为 ab mod p=ab mod φ(p) mod p
所以, x2y mod q=x2y mod φ(q) mod q=x2y mod 2k mod q
随着y的增大(约30次), x2y mod q 将变1,此时 x2y mod p 为一个定值
故可以用线段树维护区间和,每次查询就是简单的线段树区间求和
对于平方操作,维护每个区间是否已经稳定,对于稳定的区间直接返回,否则进入下层继续更新
注意p的值非常大,需要用unsigned long long以及类似快速幂的mul_mod才不会爆
/**
* Copyright (c) 2015 Authors. All rights reserved.
*
* FileName: D.cpp
* Author: Beiyu Li
* Date: 2015-05-25
*/
#include
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
typedef unsigned long long ULL;
const int maxn = 100000 + 5;
const ULL mod = 9223372034707292160ULL;
int n, m;
ULL a[maxn];
ULL sum[1<<18];
bool stb[1<<18];
ULL mul_mod(ULL a, ULL b, ULL m = mod)
{
ULL res = 0;
for (; b; a = (a + a) % m, b >>= 1) if (b & 1) res = (res + a) % m;
return res;
}
void build(int o, int l, int r)
{
if (l == r) {
stb[o] = false; sum[o] = a[l];
return;
}
int mid = (l + r) >> 1, lc = o * 2, rc = o * 2 + 1;
build(lc, l, mid); build(rc, mid + 1, r);
sum[o] = (sum[lc] + sum[rc]) % mod;
stb[o] = (stb[lc] && stb[rc]);
}
ULL query(int o, int l, int r, int s, int t)
{
if (s <= l && r <= t) return sum[o];
int mid = (l + r) >> 1, lc = o * 2, rc = o * 2 + 1;
ULL res = 0;
if (s <= mid) res = (res + query(lc, l, mid, s, t)) % mod;
if (t > mid) res = (res + query(rc, mid + 1, r, s, t)) % mod;
return res;
}
void update(int o, int l, int r, int s, int t)
{
if (stb[o]) return;
if (l == r) {
a[l] = mul_mod(a[l], a[l]);
stb[o] = (sum[o] == a[l]);
sum[o] = a[l];
return;
}
int mid = (l + r) >> 1, lc = o * 2, rc = o * 2 + 1;
if (s <= mid) update(lc, l, mid, s, t);
if (t > mid) update(rc, mid + 1, r, s, t);
sum[o] = (sum[lc] + sum[rc]) % mod;
stb[o] = (stb[lc] && stb[rc]);
}
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &m);
For(i,1,n) scanf("%llu", &a[i]);
build(1, 1, n);
printf("Case #%d:\n", ++cas);
ULL res = 0;
while (m--) {
int l, r;
scanf("%d%d", &l, &r);
res = (res + query(1, 1, n, l, r)) % mod;
printf("%llu\n", res);
update(1, 1, n, l, r);
}
}
return 0;
}
DRD有N场考试,每场考试的开始时间为 ei ,持续时间为 li
对于每场考试,需要在考前进行 ri 个小时的复习,问DRD能否顺利完成这N场考试
其中,每场考试的复习时间不需要连续,考试进行期间不能复习
贪心,先考先复习
按照开始时间对所有考试排序,然后依次进行
对于某场考试前的空余时间,选择最先考的进行复习
/**
* Copyright (c) 2015 Authors. All rights reserved.
*
* FileName: E.cpp
* Author: Beiyu Li
* Date: 2015-05-25
*/
#include
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = 100000 + 5;
int n;
struct Exam {
int r, e, l;
bool operator<(const Exam &ex) const { return e < ex.e; }
} a[maxn];
bool solve()
{
sort(a, a + n);
LL clk = 0, now = 0;
rep(i,n) {
LL res = a[i].e - clk;
if (res < 0) return false;
while (now < n && res) {
if (a[now].r <= res) res -= a[now++].r;
else a[now].r -= res, res = 0;
}
if (now <= i) return false;
clk = a[i].e + a[i].l;
}
return true;
}
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
rep(i,n) scanf("%d%d%d", &a[i].r, &a[i].e, &a[i].l);
printf("Case #%d: %s\n", ++cas, solve()? "YES": "NO");
}
return 0;
}
某个大小为N的集合有9个子集,现在给出它们之间的包含关系(形如A是B的子集)
问这9个子集有多少种可能的情况
由于N个元素的包含关系相互独立
故只需要算出对于一个元素的所有方案数X,则 XN 就是答案
其中X = 32可通过考察样例得出,也可以暴力算得
/**
* Copyright (c) 2015 Authors. All rights reserved.
*
* FileName: F.cpp
* Author: Beiyu Li
* Date: 2015-05-25
*/
#include
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const int maxm = 100000 + 5;
int n;
int m, a[maxm];
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
m = 0; a[m++] = 1;
while (n--) {
rep(i,m) a[i] *= 32;
rep(i,m) if (a[i] >= 10) {
if (i + 1 == m) a[m++] = a[i] / 10;
else a[i+1] += a[i] / 10;
a[i] %= 10;
}
}
printf("Case #%d: ", ++cas);
for (int i = m - 1; i >= 0; --i) printf("%d", a[i]);
puts("");
}
return 0;
}
给出一棵N个节点的树,每个节点有一个权值
要求在树上找出K条从根节点到叶子节点的路径,使得被路径覆盖到的节点的权值和最大
输出最大的权值和,其中被多次覆盖的节点只能累加一次
贪心,每次找出权值和最大的一条路径,累加后删除该条路径上的点
粗略的证明:
如果初始状态下权值和最大的路径(记作X)不在最终的K条路径中,则找出其中与X重叠最深的路径中的一条,将其替换为X后结果必然增大,故最终的K条路径中必然包含初始权值最大的一条路径。
而上述贪心等价于将每个节点的值,累加到其子树中权值最大的叶子上
这一过程可通过DFS实现,具体的细节可参见下面的代码
最后筛选出所有叶子中权值最大的K个,累加即为答案
/**
* Copyright (c) 2015 Authors. All rights reserved.
*
* FileName: G.cpp
* Author: Beiyu Li @gmail.com>
* Date: 2015-05-25
*/
#include
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = 100000 + 5;
int psz;
struct Edge {
int v;
Edge *next;
} epl[maxn*2], *e[maxn];
void add_edge(int u, int v)
{
Edge *i = epl + psz++;
i->v = v; i->next = e[u]; e[u] = i;
}
int n, k;
LL val[maxn];
int best[maxn];
int sz;
LL vec[maxn];
void dfs(int u, int pa)
{
int p = -1;
for (Edge *i = e[u]; i; i = i->next) {
int v = i->v;
if (v == pa) continue;
dfs(v, u);
if (p == -1 || val[best[v]] > val[p]) p = best[v];
}
if (p == -1) best[u] = u;
else val[p] += val[u], val[u] = -1, best[u] = p;
}
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
psz = 0;
memset(e, 0, sizeof(e));
scanf("%d%d", &n, &k);
rep(i,n) scanf("%lld", &val[i]);
rep(i,n-1) {
int u, v;
scanf("%d%d", &u, &v);
--u; --v;
add_edge(u, v);
add_edge(v, u);
}
dfs(0, -1);
sz = 0;
rep(i,n) if (~val[i]) vec[sz++] = -val[i];
nth_element(vec, vec + k, vec + sz);
LL res = 0;
rep(i,min(k,sz)) res += -vec[i];
printf("Case #%d: %lld\n", ++cas, res);
}
return 0;
}
给出平面上的N个点
对于平面上的任意一点p,要求任何一条通过p且不经过上面N个点的直线,其两侧的点数都不少于 ⌊N3⌋
问符合上面要求的点形成的区域的面积是多少
半平面交,考察N个点中所有点对形成的有向直线
若直线的右侧刚好有 N3−1 个点,则该区域内不存在符合要求的点
反之对于任意一个不符合要求的点,也一定在某个这样的区域内
故该直线左侧对应的半平面是答案可能存在的区域
对所有这样的半平面求交,所得多边形的面积即为所求
/**
* Copyright (c) 2015 Authors. All rights reserved.
*
* FileName: H.cpp
* Author: Beiyu Li
* Date: 2015-05-25
*/
#include
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const double eps = 1e-10;
int sgn(double x) { return x < -eps? -1: x > eps; }
typedef complex<double> Point;
typedef complex<double> Vector;
#define X real()
#define Y imag()
double cross(Vector u, Vector v) { return u.X * v.Y - u.Y * v.X; }
struct Line {
Point p; Vector v; double a;
Line(Point p = 0, Vector v = 0): p(p), v(v) { a = arg(v); }
};
bool line_inter(Line a, Line b, Point &p)
{
double c = cross(a.v, b.v);
if (!sgn(c)) return false;
p = a.p + a.v * (cross(b.v, a.p - b.p) / c);
return true;
}
typedef vector Polygon;
double polygon_area(const Polygon &g)
{
double s = 0;
for (int i = 1; i < (int)g.size() - 1; ++i)
s += cross(g[i] - g[0], g[i+1] - g[0]);
return fabs(s) / 2.0;
}
int on_left(Point p, Line l) { return sgn(cross(p - l.p, l.v)) < 0; }
bool cmp(Line a, Line b)
{
return sgn(a.a - b.a)? a.a < b.a: cross(a.v, b.p - a.p) < 0;
}
void halfplane_inter(Line l[], int n, Polygon &g)
{
vector q(n);
int head = 0, tail = 0;
sort(l, l + n, cmp);
for (int i = 1; i < n; ++i) {
if (!sgn(l[i].a - l[i-1].a)) continue;
while (head < tail && !on_left(q[tail-1], l[i])) --tail;
while (head < tail && !on_left(q[head], l[i])) ++head;
l[++tail] = l[i];
if (head < tail) line_inter(l[tail-1], l[tail], q[tail-1]);
}
while (head < tail && !on_left(q[tail-1], l[head])) --tail;
if (head < tail) line_inter(l[tail], l[head], q[tail]);
g.assign(q.begin() + head, q.begin() + tail + 1);
}
typedef pair<double, int> Pdi;
const int maxn = 1000 + 5;
int n, k;
Point p[maxn];
Line l[maxn*maxn];
Pdi vec[maxn];
double solve()
{
int m = 0;
rep(i,n) {
int sz = 0;
rep(j,n) if (j != i)
vec[sz++] = Pdi(arg(p[j] - p[i]), j);
sort(vec, vec + sz);
int cnt = 0, now = 0;
rep(j,sz) {
int t = vec[j].second;
if (now == j) ++cnt, now = (now + 1) % sz;
while (on_left(p[vec[now].second],
Line(p[i], p[t] - p[i])))
++cnt, now = (now + 1) % sz;
if (cnt-- == k) l[m++] = Line(p[i], p[i] - p[t]);
}
}
Polygon g;
halfplane_inter(l, m, g);
return polygon_area(g);
}
int main()
{
srand((int)time(NULL));
int T, cas = 0;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
k = n / 3;
rep(i,n) {
int x, y;
scanf("%d%d", &x, &y);
p[i] = Point(x, y);
}
printf("Case #%d: %.10f\n", ++cas, solve());
}
return 0;
}
对于一个长度 n=2k 的序列 an ,给出如下的编码方式
考察k阶编码的系数矩阵 Mk
/**
* Copyright (c) 2015 Authors. All rights reserved.
*
* FileName: I.cpp
* Author: Beiyu Li
* Date: 2015-05-25
*/
#include
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = (1 << 20) + 5;
int k, n;
LL a[maxn], b[maxn];
void dfs(int s, int n)
{
if (n == 1) {
a[s] = b[s];
return;
}
int n2 = n / 2;
LL t = b[s+n-1] - b[s+n2-1];
rep(i,n2) b[s+i] = (b[s+i] + b[s+n2+i] - t) / 2;
rep(i,n2) b[s+n2+i] -= b[s+i];
dfs(s, n2);
dfs(s + n2, n2);
}
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
scanf("%d", &k);
n = 1 << k;
rep(i,n) scanf("%lld", &b[i]);
dfs(0, n);
printf("Case #%d:", ++cas);
rep(i,n) printf(" %lld", a[i]);
puts("");
}
return 0;
}
对一个M × N矩阵进行K次染色,每次随机选取两个格子作为被染色子矩阵的两个角
问最终被染色的格子的个数期望,其中多次被染色的格子只记一次
由于期望的线性性质,答案等于每个格子被染色的概率的和
若某个格子在一次操作中被染色的概率为p,则K次操作后被染色的概率为 1−(1−p)K
而对于一次操作的概率p,可以使用分类讨论或容斥原理计算
/**
* Copyright (c) 2015 Authors. All rights reserved.
*
* FileName: J.cpp
* Author: Beiyu Li @gmail.com>
* Date: 2015-05-25
*/
#include
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
double sqr(double x) { return x * x; }
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
double res = 0;
rep(i,n) rep(j,m) {
double p = 0;
p += (sqr(i) + sqr(n - i - 1)) * sqr(m);
p += sqr(n) * (sqr(j) + sqr(m - j - 1));
p -= (sqr(i) + sqr(n - i - 1)) *
(sqr(j) + sqr(m - j - 1));
p /= sqr(n) * sqr(m);
res += 1 - pow(p, k);
}
printf("Case #%d: %.0f\n", ++cas, res);
}
return 0;
}
给出随机生成的两个序列A[]和B[],找出集合 C={A[i]+B[j] | 1≤i,j≤n} 中第k大的元素
由于数列是随机生成的,故集合中重复的元素较少,可以通过优先队列求解
先对A[]和B[]排序、去重,将每个A[i]对应B[]的最后一个位置,并将它们的和插入优先队列中
每次找出队列中的最大值,然后删除与之相等的所有值
若被删除的A[i]的对应位置可以向前调整,则将调整后的和重新插入队列中
执行K次或队列为空时结束
/**
* Copyright (c) 2015 Authors. All rights reserved.
*
* FileName: K.cpp
* Author: Beiyu Li
* Date: 2015-05-25
*/
#include
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = 100000 + 5;
int n, m, k;
int a[maxn], b[maxn], p[maxn];
set st;
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &k); m = n;
rep(i,n) scanf("%d", &a[i]);
rep(i,m) scanf("%d", &b[i]);
sort(a, a + n);
n = unique(a, a + n) - a;
sort(b, b + m);
m = unique(b, b + m) - b;
st.clear();
rep(i,n) {
p[i] = m - 1;
st.insert(Pii(a[i] + b[p[i]], i));
}
int now;
while (!st.empty() && k--) {
now = st.rbegin()->first;
while (!st.empty() && st.rbegin()->first == now) {
int i = st.rbegin()->second;
st.erase(--st.end());
if (p[i]) st.insert(Pii(a[i] + b[--p[i]], i));
}
}
printf("Case #%d: %d\n", ++cas, k == -1? now: -1);
}
return 0;
}
卡牌集齐一套“RGB”就能扔一套技能,现给出他的手牌,问最多能扔几套技能
统计R、G、B出现的次数,最小值就是答案
/**
* Copyright (c) 2015 Authors. All rights reserved.
*
* FileName: L.cpp
* Author: Beiyu Li
* Date: 2015-05-25
*/
#include
using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define For(i,s,t) for (int i = (s); i <= (t); ++i)
#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)
typedef long long LL;
typedef pair<int, int> Pii;
const int inf = 0x3f3f3f3f;
const LL infLL = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = 1000 + 5;
int n;
char s[maxn];
int main()
{
int T, cas = 0;
scanf("%d", &T);
while (T--) {
scanf("%d%s", &n, s);
int r = 0, g = 0, b = 0;
rep(i,n) {
if (s[i] == 'R') ++r;
if (s[i] == 'G') ++g;
if (s[i] == 'B') ++b;
}
printf("Case #%d: %d\n", ++cas, min(r, min(g, b)));
}
return 0;
}