模拟赛小结:2018 China Collegiate Programming Contest Final (CCPC-Final 2018)
比赛链接:传送门
跌跌撞撞6题摸银。
封榜后两题,把手上的题做完了还算舒服。就是罚时有点高。
开出了一道奇奇怪怪的题(K),然后ccpcf银应该比区域赛银要难吧,反正很开心qwq。
Problem A. Mischievous Problem Setter 00:14 (-2) Solved by Dancepted
良心签到题。WA2吃乳猪。
代码:
#include <iostream>
#include <cmath>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 100005
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x)
using namespace std;
typedef long long ll;
typedef double db;
/** fast read **/
template <typename T>
inline void read(T &x) {
x = 0; T fg = 1; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -1;
ch = getchar();
}
while (isdigit(ch)) x = x*10+ch-'0', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
int len = 0; char c[21]; if (x < 0) putchar('-'), x = -x;
do{++len; c[len] = x%10 + '0';} while (x /= 10);
for (int i = len; i >= 1; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); }
struct Node{
int d, t;
bool operator < (const Node& x) const {
return d < x.d;
}
}nodes[N];
int main() {
fast;
int T; cin >> T;
for (int kase = 1; kase <= T; kase++) {
int n, m; cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> nodes[i].d;
}
for (int i = 1; i <= n; i++) {
cin >> nodes[i].t;
}
sort(nodes+1, nodes+1+n);
int ans = 0;
for (int i = 1; i <= n; i++) {
if (nodes[i].t <= m) {
m -= nodes[i].t;
ans++;
}
else {
break;
}
}
cout << "Case " << kase << ": " << ans << endl;
}
return 0;
}
Problem L. Ultra Weak Goldbach's Conjecture 00:47(+) Solved by xk (miller rabin + 素数密度 + 哥德巴赫猜想)
根据素数密度为$log^{2}N$的结论,可以用米勒-拉宾的板子O(logn)判断大素数,暴力找出比n小的最大的一个大素数。
哥德巴赫猜想在小数据范围内成立,剩下部分如果是奇数就分成2 + 2 + 3 + 两个素数,如果是偶数就是2 + 2 + 2 + 两个素数。
(xk才是真正的数学选手,我连哥德巴赫猜想都不知道,就是打酱油的)
代码:$O(T × log^{3}N)$
#include <iostream>
#include <cmath>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define INF 0x3f3f3f3f
#define sz(x) ((int)x.size())
#define mp(a,b) make_pair(a, b)
#define endl '\n'
using namespace std;
typedef long long ll;
typedef double db;
int random(int l, int r)
{
return rand() % (r - l) + l;
}
ll fmul(ll a, ll b, ll mod)
{
a %= mod;
ll res = 0;
for(;b;b>>=1) {
if(b & 1) res = (res + a) % mod;
a = (a + a) % mod;
}
return res;
}
ll fpow(ll a, ll b, ll mod)
{
ll res = 1;
for(;b;b>>=1) {
if(b & 1) res = fmul(res, a, mod);
a = fmul(a, a, mod);
}
return res;
}
bool witness(ll a, ll n, ll u, ll t)
{
ll x0 = fpow(a, u, n), x1;
for(int i = 1; i <= t; i++)
{
x1 = fmul(x0, x0, n);
if(x1 == 1 && x0 != 1 && x0 != n - 1) return false;
x0 = x1;
}
if(x1 != 1) return false;
return true;
}
bool isprime(ll n, int times = 20)
{
if(n == 2) return true;
if(n < 2 || !(n & 1)) return false;
ll u = n - 1, t = 0;
while(u % 2 == 0) {
t++;
u>>=1;
}
while(times--)
{
ll a = random(1, n - 1);
if(!witness(a, n, u, t)) return false;
}
return true;
}
int main()
{
srand(time(0));
fast;
int T;
cin >> T;
for(int kase = 1; kase <= T; kase++)
{
cout << "Case " << kase << ": ";
ll n;
cin >> n;
if(n < 12) {
cout << "IMPOSSIBLE\n";
continue;
}
for(ll i = n - 10; ; i--)
{
if(isprime(i)) {
n -= i;
cout << i;
break;
}
}
if(n & 1)
{
cout << " 2 2 3";
n -= 7;
}
else
{
cout << " 2 2 2";
n -= 6;
}
for(ll i = 2; i <= n / 2; i++)
{
if(isprime(i) && isprime(n - i))
{
cout << ' ' << i << ' ' << n - i << endl;
break;
}
}
}
}
Problem G. Pastoral Life in Stardew Valley 01:13 (+) Solved by Dancepted (平方和公式)
设$f_{n, m}$表示n × m的草地上放稻草人的方案数,则:
$f_{n, m} = \sum_{i=1}^{n-2} \sum_{j=1}^{m-2}(n-i+1) × (m-j+1) = \frac{(n-1)(n-2) × (m-1)(m-2)}{4}$
设$F_{n, m}$表示n × m的土地上的答案,则:
$F_{n, m} = \sum_{i=3}^{n}\sum_{j=3}^{m} (n-i+1)×(m-j+1)×f_{i, j} $
$= \sum_{i=3}^{n}\sum_{j=3}^{m} (n-i+1)×(m-j+1)×\frac{1}{4}i(i-1) × i(i-1)$
$= \frac{1}{4} \sum_{i=3}^{n}(n-i+1)(i-1)(i-2)\sum_{j=3}^{m}(m-j+1)(j-1)(j-2)$
令$g_{x} = \frac{1}{2} \sum_{i=3}^{x}(x-i+1)(i-1)(i-2)$,则$F_{n, m} = g_{n} * g_{m}$。
考虑预处理$g_{x}$:
①:$g_{3} = 1$
②:若已知$g_{x} = \frac{1}{2} \sum_{i=3}^{x}(x-i+1)(i-1)(i-2)$,则:
$g_{x+1} = \frac{1}{2} \sum_{i=3}^{x+1}(x-i+1+1)(i-1)(i-2)$
$= \frac{1}{2} \sum_{i=3}^{x+1}(x-i+1)(i-1)(i-2) + \frac{1}{2}\sum_{i=3}^{x+1}(i-1)(i-2) $
令$h_{x} = \frac{1}{2}\sum_{i=3}^{x}(i-1)(i-2) $,则:
$g_{x+1} = g_{x} + h_{x}$,其中,用平方和公式和等差数列求和公式可以O(1)地计算$h_{x}$。
代码:O(T + N)
#include <iostream>
#include <cmath>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 100005
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x)
using namespace std;
typedef long long ll;
typedef double db;
/** fast read **/
template <typename T>
inline void read(T &x) {
x = 0; T fg = 1; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -1;
ch = getchar();
}
while (isdigit(ch)) x = x*10+ch-'0', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
int len = 0; char c[21]; if (x < 0) putchar('-'), x = -x;
do{++len; c[len] = x%10 + '0';} while (x /= 10);
for (int i = len; i >= 1; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); }
#define md 1000000007
ll mul(ll a, ll b) {
return a * b % md;
}
ll add(ll a, ll b) {
ll res = (a+b) % md;
if (res < 0) res += md;
return res;
}
ll fpow(ll a, ll p) {
ll res = 1;
for (; p; p >>= 1) {
if (p & 1)
res = mul(res, a);
a = mul(a, a);
}
return res;
}
ll inv6, inv2;
ll g[N];
ll h(ll x) {
ll res = 0;
res = add(res, mul(mul(x, mul(x+1, 2*x+1)), inv6));
res = add(res, mul(mul(x, x+1), inv2));
res = mul(res, inv2);
return res;
}
void init() {
g[3] = 1;
for (int i = 4; i < N; i++) {
g[i] = add(g[i-1], h(i-2));
}
}
int main() {
fast;
int T; cin >> T;
inv2 = fpow(2, md-2);
inv6 = fpow(6, md-2);
init();
for (int kase = 1; kase <= T; kase++) {
int n, m; cin >> n >> m;
ll ans = mul(g[n], g[m]);
cout << "Case " << kase << ": " << ans << endl;
}
return 0;
}
Problem K. Mr. Panda and Kakin 02:36 (-2) Solved by Dancepted & xk (欧拉定理 逆元 素数密度)
根据欧拉定理的推论,$i^{a}$ mod n的循环节长度为$\phi(n)$,并且把n分解为$\sum_{p\in prime}p_{i}^{m_{i}}$后若$m_{i}$ <= 1,则$i^{a}$ mod n为纯循环(参考纯循环小数意会一下)。
那么只要能把$FLAG^{2^{30}+3}$凑成$FLAG^{1 mod \phi(n)}$就行了。
实际上$(x^{a})^{b} = x^{a×b}$,所以如果我们能求出$2^{30}+3$关于$phi(n)$的逆元,那么就有$(Flag^{2^{30}+3})^{逆元} = Flag^{1 mod \phi(n)} = Flag$。
而这个逆元是肯定存在的,因为$2^{30}+3$是一个质数,而且考虑到n的生成方式,n = p × q,phi(n) = (p-1)×(q-1)。而 p-1,q-1 < $2^{30}+3$,因此($2^{30}+3, \phi(n)$)= 1。
求$\phi(n)$的时候考虑素数密度,可以$O(log^{2}n)$暴力地找出n的两个素因子。
然后快速幂会爆long long,要用快速乘,然后这题的log又比较大,$log^{2}$会tle,所以要用O(1)的快速乘。
PS:第一次写脑抽了以为$(x^{a})^{c} = x^{a+b}$,幸好没过样例。
PPS:这里吹爆jls在ccpc-camp讲的数论div2,听完之后碰到欧拉定理完全不虚,然后在comet oj的直播回放里就可以看(jls的盛世美颜)了。
代码:O(T×logn)
#include <iostream>
#include <cmath>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 100005
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x)
using namespace std;
typedef long long ll;
typedef double db;
typedef long double ldb;
/** fast read **/
template <typename T>
inline void read(T &x) {
x = 0; T fg = 1; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -1;
ch = getchar();
}
while (isdigit(ch)) x = x*10+ch-'0', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
int len = 0; char c[21]; if (x < 0) putchar('-'), x = -x;
do{++len; c[len] = x%10 + '0';} while (x /= 10);
for (int i = len; i >= 1; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); }
ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a%b);
}
ll fmul(ll a, ll b, ll md) {
a %= md, b %= md;
ll c = (ldb) a * b / md;
ll ans = a * b - c * md;
if (ans < 0) ans += md;
else if (ans >= md) ans -= md;
return ans;
}
ll fpow(ll a, ll p, ll md) {
ll res = 1;
for (; p; p >>= 1) {
if (p & 1)
res = fmul(res, a, md);
a = fmul(a, a, md);
}
return res;
}
ll exgcd(ll a, ll b, ll &x, ll &y) {
if (a == 0 && b == 0) return -1;
if (b == 0) {x = 1, y = 0; return a;}
ll d = exgcd(b, a%b, y, x);
y -= a/b*x;
return d;
}
ll mod_reverse(ll a, ll n) {
ll x, y;
ll d = exgcd(a, n, x, y);
if (d == 1) return (x % n + n) % n;
return -1;
}
int main() {
// fast;
int T; cin >> T;
for (int kase = 1; kase <= T; kase++) {
ll n, c; read(n, c);
ll g = gcd(n, c);
ll flag = 0, phin = 0;
if (g == 1) {
ll x = sqrt(n+0.5);
if (x % 2 == 0)
x--;
for (ll i = x; i >= 0; i -= 2) {
if (n % i == 0) {
phin = (i-1) * (n/i -1);
break;
}
}
}
else {
phin = (g-1) * (n/g - 1);
}
ll p = mod_reverse((1<<30)+3, phin);
flag = fpow(c, p, n);
printf("Case %d: %I64d\n", kase, flag);
}
return 0;
}
/*
3
181857896263 167005790444
218128229323 156323229335
352308724847 218566715941
*/
Problem I. Cockroaches 04:19 (-1) Solved by Dancepted & lh & xk
大概是个思维题吧。。。封榜20分钟才调出来qwq。(不过好像是第一次封榜后过题?)
能消灭的最多的小强数量只有两种情况。设小强数最多的行和列对应的小强数是r和c,那么能消灭最多的数量要么是r+c,要么是r+c-1。
然后遍历小强数最多的行(列)上的小强,统计能消灭r+c和r+c-1的方案数就行了。
具体的就是遍历小强数最多的行(列)上的小强的时候,看这些小强是否恰巧在小强数最多的列(行),如果在的话,说明激光中心在这个小强所在点上时,能消灭的数量是r+c-1而不是r+c。
若r+c的数量为0,那么用同样的方法再统计一下小强数次多的行(列)与小强数最多的列(行)对r+c-1的贡献就行了。
小强的坐标上限是1e9,要离散化一下。
特别地:依次最多消灭小强数为2的时候要特判一下,防止在两个不同点消灭了两个相同小强。
代码:O(T×nlogn)
#include <iostream>
#include <cmath>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <string>
#include <queue>
#include <stack>
#include <iomanip>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 200005
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl '\n'
#define lowbit(x) (x&-x)
using namespace std;
typedef long long ll;
typedef double db;
/** fast read **/
template <typename T>
inline void read(T &x) {
x = 0; T fg = 1; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -1;
ch = getchar();
}
while (isdigit(ch)) x = x*10+ch-'0', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
int len = 0; char c[21]; if (x < 0) putchar('-'), x = -x;
do{++len; c[len] = x%10 + '0';} while (x /= 10);
for (int i = len; i >= 1; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); }
int n;
vector<int> vals;
map<int, int> id;
// int id[N<<1];
struct Node{
int r, c;
}ns[N];
vector <Node> vc[N], vr[N];
int cntr1 = -1, cntr2 = -1, lenr1 = -1, lenr2 = -1;
int cntc1 = -1, cntc2 = -1, lenc1 = -1, lenc2 = -1;
void init() {
sort(vals.begin(), vals.end());
vals.erase(unique(vals.begin(), vals.end()), vals.end());
for (int i = 0; i < sz(vals); i++) {
id[vals[i]] = i;
vc[i].clear();
vr[i].clear();
}
for (int i = 1; i <= n; i++) {
int idr = id[ns[i].r], idc = id[ns[i].c];
vr[idr].push_back(ns[i]);
vc[idc].push_back(ns[i]);
}
cntr1 = -1, cntr2 = -1, lenr1 = -1, lenr2 = -1;
cntc1 = -1, cntc2 = -1, lenc1 = -1, lenc2 = -1;
for (int i = 0; i < sz(vals); i++) {
if (sz(vr[i]) > lenr1) {
lenr2 = lenr1;
cntr2 = cntr1;
lenr1 = sz(vr[i]);
cntr1 = 1;
}
else if (sz(vr[i]) == lenr1) {
cntr1++;
}
else if (sz(vr[i]) > lenr2) {
lenr2 = sz(vr[i]);
cntr2 = 1;
}
else if (sz(vr[i]) == lenr2) {
cntr2++;
}
if (sz(vc[i]) > lenc1) {
lenc2 = lenc1;
cntc2 = cntc1;
lenc1 = sz(vc[i]);
cntc1 = 1;
}
else if (sz(vc[i]) == lenc1) {
cntc1++;
}
else if (sz(vc[i]) > lenc2) {
lenc2 = sz(vc[i]);
cntc2 = 1;
}
else if (sz(vc[i]) == lenc2) {
cntc2++;
}
}
}
int main() {
fast;
int T; cin >> T;
for (int kase = 1; kase <= T; kase++) {
cin >> n;
id.clear();
vals.clear();
for (int i = 1; i <= n; i++) {
read(ns[i].r, ns[i].c);
vals.push_back(ns[i].r);
vals.push_back(ns[i].c);
}
init();
ll ans1 = lenc1 + lenr1, cnt1 = 0;
ll ans2 = lenc1 + lenr1 - 1, cnt2 = 0;
for (int i = 0; i < sz(vals); i++) {
if (sz(vc[i]) == lenc1) {
cnt1 += cntr1;
if (lenr2 == lenr1 - 1) {
cnt2 += cntr2;
}
for (Node &tmp : vc[i]) {
if (sz(vr[id[tmp.r]]) == lenr1) {
// share same point
cnt1--;
cnt2++;
}
else if (lenr2 == lenr1 - 1 && sz(vr[id[tmp.r]]) == lenr2) {
cnt2--;
}
}
}
else if (lenc2 == lenc1 - 1 && sz(vc[i]) == lenc2) {
cnt2 += cntr1;
for (Node &tmp: vc[i]) {
if (sz(vr[id[tmp.r]]) == lenr1) {
// share same point
cnt2--;
}
}
}
}
ll ans = 0, cnt = 0;
if (cnt1 > 0) {
ans = ans1, cnt = cnt1;
}
else {
ans = ans2, cnt = cnt2;
}
if (ans == 2) {
cnt = 1LL * n * (n-1) / 2;
}
printf("Case %d: %I64d %I64d\n", kase, ans, cnt);
}
return 0;
}
Problem B. Balance of the Force 04:35(+) Solved by lh(贪心)
不能放在同一边的两个人连一条边,如果得到的图中有奇数环,则不可能。
然后枚举最小的能力值。贪心地寻找最小的最大值。
枚举下一个最小的能力值时,仅有当前最小能力值所在的环,和下一个最小能力值所在的环对应的能力值要更新,所以整个贪心可以是O(N)的。
代码:O(T×N)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <cstring>
#define N 200005
#define INF 0x3f3f3f3f
#define fi first
#define se second
using namespace std;
typedef pair<int,int> pii;
/** fast read **/
template <typename T>
inline void read(T &x) {
x = 0; T fg = 1; char ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') fg = -1;
ch = getchar();
}
while (isdigit(ch)) x = x*10+ch-'0', ch = getchar();
x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
int len = 0; char c[21]; if (x < 0) putchar('-'), x = -x;
do{++len; c[len] = x%10 + '0';} while (x /= 10);
for (int i = len; i >= 1; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); }
int T;
int n, m, ednum, top, col[N];
int w[N][2];
struct node
{
int be, w;
bool operator<(const node &other)const
{
return w < other.w;
}
} s[N << 1];
struct Unite
{
int cur, maxn[2], minx[2];
} st[N];
int hed[N << 1], nxt[N << 1], to[N << 1];
void add(int u, int v)
{
to[++ednum] = v;
nxt[ednum] = hed[u], hed[u] = ednum;
}
bool dfs(int v)
{
st[top].maxn[0] = max(st[top].maxn[0], w[v][col[v]]), st[top].minx[0] = min(st[top].minx[0], w[v][col[v]]);
st[top].maxn[1] = max(st[top].maxn[1], w[v][col[v] ^ 1]), st[top].minx[1] = min(st[top].minx[1], w[v][col[v] ^ 1]);
for (int i = hed[v]; i; i = nxt[i])
{
int u = to[i];
if (col[u] == col[v])
return false;
if (col[u] != -1)
continue;
col[u] = 1 ^ col[v];
if (dfs(u) == false)
return false;
}
return true;
}
int save[N], ansmax;
bool reduce()
{
while (top)
{
int id = save[top];
if (st[id].cur == 1)
return false;
ansmax = max(ansmax, st[id].maxn[1]), st[id].cur = 1, --top;
}
return true;
}
int main() {
read(T);
int u, v, cnt;
int casecnt = 0;
while (T--)
{
++casecnt;
read(n, m), ednum = top = 0, memset(hed, 0, sizeof(int) * (n + 1)), memset(col, -1, sizeof(int) * (n + 1));
for (int i = 1;i <= m; ++i)
read(u, v), add(u, v), add(v, u);
for (int i = 1;i <= n; ++i)
read(w[i][0], w[i][1]);
bool flag = true;
ansmax = 0, top = 0, cnt = 0;
int ans = INF;
for (int i = 1;i <= n; ++i)
{
if (col[i] != -1) continue;
++top, st[top].cur = 0, st[top].maxn[0] = st[top].maxn[1] = 0;
st[top].minx[0] = st[top].minx[1] = INF, col[i] = 0, flag &= dfs(i);
if (flag == false)
break;
if (st[top].minx[0] > st[top].minx[1])
swap(st[top].minx[0], st[top].minx[1]), swap(st[top].maxn[0], st[top].maxn[1]);
if (st[top].maxn[0] >= st[top].maxn[1])
st[top].cur = 1;
else
s[++cnt] = node{top, st[top].minx[0]};
s[++cnt] = node{top, st[top].minx[1]};
ansmax = max(ansmax, st[top].maxn[st[top].cur]);
}
printf("Case %d: ", casecnt);
if (flag == false)
{
puts("IMPOSSIBLE");
continue;
}
sort(s + 1, s + 1 + cnt);
int i = 1;
top = 0;
while (flag && i <= cnt)
{
ans = min(ans, ansmax - s[i].w);
save[++top] = s[i].be;
if (s[i].w != s[i + 1].w)
{
flag &= reduce();
if (!flag)
break;
}
++i;
}
write(ans), putchar('\n');
}
return 0;
}
还有不到一周就是CCPC-Final了,这周每两天一套题,冲鸭。
总结:
浮躁的菜逼选手贡献全部罚时。