1 条题解
-
0
标题来源:sasakure 的《Apollo》。小心 。
其实吧,抛开细节和码量(参考数据:我的代码有 , 个
if)不谈,这个题挺有趣的。我是一个 Sub 一个 Sub 写过来的。因为太难写了。
每个小部分只放核心代码,不然太长了。完整代码在最后。
讨论每个 Sub 的时候会排除做前面的 Sub 时已经判掉的情况。
Subtask1
这个 Subtask 还是非常简单的。显然把所有加在一起,判断总和是不是质数。由于数据规模稍大,以及后面要写爆搜对时间有一定要求,为了效率,我用了 Miller-Rabin。
if (k == 1){ for (int i = 1; i <= n; i++) sum += a[i]; if (isp(sum)){ cout << "1\n" << n << " "; for (int i = 1; i <= n; i++) cout << a[i] << " "; cout << "\n"; }else{ cout << "0\n" << n << " "; for (int i = 1; i <= n; i++) cout << a[i] << " "; cout << "\n"; } }Subtask2
数据很小,直接状压爆搜。
void dfs(int S, int now, int dep){ // cerr << S << " " << mn[S] << " " << now << "\n"; if (S == (1 << n) - 1 && dep != k + 1) return; if (now >= mn[S]) return; mn[S] = now; if (dep >= k + 1) return; for (int T = 1; T < (1 << n); T++){ if (S & T) continue; long long sum = 0; for (int i = 1; i <= n; i++) if (T & (1 << i - 1)) sum += a[i]; // cerr << T << " " << sum << " " << isp(sum) << "\n"; // system("pause"); dfs(S | T, now + isp(sum), dep + 1); } } void dfs2(int S, int now, int dep){ // cerr << S << " " << now << " " << dep << "\n"; // cerr << mn[S] << "\n"; // if (now > mn[S]) // return; if (fnd) return; if (dep > k + 1) return; if (dep == k + 1 && S == (1 << n) - 1){ // cerr << now << " " << mn[S] << "\n"; if (now == mn[S]){ fnd = 1; for (int i = 1; i <= k; i++){ cout << ans[i].size() << " "; for (auto u : ans[i]) cout << u << " "; cout << "\n"; ans[i].clear(); } } return; }else if (dep == k + 1) return; for (int T = 1; T < (1 << n); T++){ if (S & T) continue; long long sum = 0; for (int i = 1; i <= n; i++) if (T & (1 << i - 1)){ sum += a[i]; ans[dep].emplace_back(a[i]); } dfs2(S | T, now + isp(sum), dep + 1); ans[dep].clear(); } }Subtask3
上面的爆搜跑的很慢,可以改成记忆化,这样子优化会相当大,可以通过 ,。但是当 大的时候会挂掉。所以当 的时候搜 ,因为 的情况可能会很多,这样简化会比较好。 边界不多,跑不动就跑不动了。
void dfs(int S, int now, int dep){ // cerr << S << " " << mn[S] << " " << now << "\n"; if (S == (1 << n) - 1 && dep != k + 1) return; if (now >= mn[S]) return; if (S == (1 << n) - 1){ for (int i = 1; i <= k; i++) ans[i] = tmp[i]; } mn[S] = now; if (dep >= k + 1) return; for (int T = 1; T < (1 << n); T++){ if (S & T) continue; long long sum = 0; for (int i = 1; i <= n; i++) if (T & (1 << i - 1)){ sum += a[i]; tmp[dep].emplace_back(a[i]); } // cerr << T << " " << sum << " " << isp(sum) << "\n"; // system("pause"); dfs(S | T, now + isp(sum), dep + 1); tmp[dep].clear(); } }Subtask4
是偶数且没有 ,显然奇素数可以两两配对,如果 ,这样配 组然后把剩下的直接分成一组就可以了。这种分法保证了每组和为偶数,奇异序列数量为 ;否则一定有 组是单个的,其余的两两分成一组。
if (!(n & 1)){ if (maimai > 2){ if (k <= n / 2){ cout << "0\n"; for (int i = 1; i <= k - 1; i++) cout << "2 " << a[i * 2 - 1] << " " << a[i * 2] << "\n"; cout << n - 2 * (k - 1) << " "; for (int i = (k - 1) * 2 + 1; i <= n; i++) cout << a[i] << " "; cout << "\n"; }else{ cout << 2 * k - n << "\n"; for (int i = 1; i <= 2 * k - n; i++) cout << "1 " << a[i] << "\n"; for (int i = 2 * k - n + 1; i <= n; i += 2) cout << "2 " << a[i] << " " << a[i + 1] << "\n"; } } }Subtask5
难度从这里开始。
首先分析 。这种情况和偶数差不多,把单个的拎出来,把其他的两两配掉。
然后分析 的情况。考虑证明 时答案必定为 。
证明:考虑把每个质数按照 的余数分类。根据鸽巢原理,至少有一个余数出现了 次。所以一定能够分出一组 的倍数。找出哪个出现了至少 次即可。剩下的两两一组也一定是合数。
分这三种情况讨论就做完了。
if (maimai > 2){ if (k <= n / 2){ cout << "0\n"; memset(buk, 0, sizeof buk); for (int i = 1; i <= n; i++) buk[a[i] % 3]++; for (int i = 1; i <= n; i++) flg[i] = 0; if (buk[0] >= 3){ cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 0; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 0){ cout << a[i] << " "; flg[i] = 1; ++cnt; ++tot; if (cnt == 3) break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } cout << "\n"; }else if (buk[1] >= 3){ cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 0; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 1){ cout << a[i] << " "; flg[i] = 1; ++cnt; ++tot; if (cnt == 3) break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } }else{ cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 0; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 2){ cout << a[i] << " "; flg[i] = 1; ++cnt; ++tot; if (cnt == 3) break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } } }else{ cout << 2 * k - n << "\n"; for (int i = 1; i <= 2 * k - n; i++) cout << "1 " << a[i] << "\n"; for (int i = 2 * k - n + 1; i <= n; i += 2) cout << "2 " << a[i] << " " << a[i + 1] << "\n"; } }Subtask6
现在可能有 了,但是 。
直接放可能会出问题,因为 和奇素数不能分在一起。处理方式其实很简单,有多的一个 就优先把 先拎出来,然后尽可能多配掉 和 还有 和奇数。因为 ,稍微算一下就可以发现非奇异序列一定可以在不考虑 加奇素数的情况下取到上界,这样就可以做了。
int cnt = 0; for (int i = 1; i <= n; i++){ if (a[i] == 2) ++cnt; else break; } for (int i = 1; i <= n; i++) flg[i] = 0; cout << 2 * k - n << "\n"; if (cnt & 1) cout << "1 2\n"; int qwq = (n - k); for (int i = 1 + (cnt & 1); i <= 2 * qwq + (cnt & 1); i += 2) cout << "2 " << a[i] << " " << a[i + 1] << "\n"; for (int i = 2 * qwq + (cnt & 1) + 1; i <= n; i++) cout << "1 " << a[i] << "\n";Subtask8
我先做的是这个 Subtask。
我们上面处理掉了很多情况,剩下有 并且 的情况。
首先,如果 是奇数个,可以把 个 分在一起,其他的就都可以两两分组,这样答案就是 。然后思考 是偶数个怎么做。
显然,当奇素数数量 的时候是好做的。根据前面 Subtask5 的方法处理掉奇素数就可以了。
那 呢?其实依旧可以套用上面的爆搜做,但是如果要分讨怎么办?直接分三种情况。
一、 个奇素数的情况
会发现答案依然可以为 。除去 个奇素数的三种情况,剩下的情况一定取满了每一个 的余数,把这三个放一起就可以了。
reverse一下原数列会好判一点。二、 个奇素数的情况
这里开始就要考虑给奇数加上 了。给出两个结论:
结论
的所有素数 一定满足 或者 。
证明: ,,,,均不可能为素数。
结论
对于一个奇素数 ,当且仅当 时, 和 均为素数,否则 和 必有一个数为合数。
证明:根据结论 , 和 一定为合数。
由于 ,所以当存在奇素数不为 的时候,这样配掉至多 个数,剩下的肯定够配。当有奇素数 为合数的时候,因为 ,一定有至少 个 ,一定可以把 个 凑一组( 要和后面的 合并)。这样子分组既不会超限也不会不够。
然后就是奇素数全为 的情况。显然 是一个合数。剩下的全是 ,可以轻松配掉。
至此,这一部分得到了解决。
三、 个奇素数的情况
分类讨论这个奇素数加多少是合数。
如果 是合数,那么依旧奇素数和 配掉, 个 凑一组,剩下的划分。 合并两组即可。
如果 是合数,那么奇素数和两个 配掉,剩下的直接划分。
如果是一个 并且 卡满了,会发现一定有一个 落单,所以会有 个奇异序列。特判掉。没卡满的话依然可以分出来。
讨论完这些,这个 Subtask 就完成了。
int cnt = 0; for (int i = 1; i <= n; i++){ if (a[i] == 2) ++cnt; else break; } if (cnt & 1){ cout << "0\n"; if (k == 2){ cout << "3 " << a[1] << " " << a[2] << " " << a[3] << "\n"; cout << n - 3 << " "; for (int i = 4; i <= n; i++) cout << a[i] << " "; cout << "\n"; }else{ cout << "3 " << a[1] << " " << a[2] << " " << a[3] << "\n"; int pos = 4, js = 1; while (1){ if (js == k - 1) break; cout << "2 " << a[pos] << " " << a[pos + 1] << "\n"; pos += 2; ++js; } cout << (n - pos + 1) << " "; for (int i = pos; i <= n; i++) cout << a[i] << " "; cout << "\n"; } }else{ if (n - cnt > 3){ cout << "0\n"; memset(buk, 0, sizeof buk); for (int i = 1; i <= n; i++) if (a[i] != 2) buk[a[i] % 3]++; for (int i = 1; i <= n; i++) flg[i] = 0; if (buk[0] >= 3){ cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 0; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 0){ cout << a[i] << " "; flg[i] = 1; ++cnt; ++tot; if (cnt == 3) break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } cout << "\n"; }else if (buk[1] >= 3){ cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 0; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 1){ cout << a[i] << " "; flg[i] = 1; ++cnt; ++tot; if (cnt == 3) break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } }else if (buk[2] >= 3){ cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 0; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 2 && a[i] != 2){ cout << a[i] << " "; flg[i] = 1; ++cnt; ++tot; if (cnt == 3) break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } }else{ reverse(a + 1, a + 1 + n); cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 3; int p1, p2, p3; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 0){ p1 = i; flg[i] = 1; cout << a[i] << " "; break; } } for (int i = 1; i <= n; i++){ if (a[i] % 3 == 1){ p2 = i; flg[i] = 1; cout << a[i] << " "; break; } }for (int i = 1; i <= n; i++){ if (a[i] % 3 == 2){ p3 = i; flg[i] = 1; cout << a[i] << " "; break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } } }else if (n - cnt == 1){ reverse(a + 1, a + 1 + n); int pos, cnt = 1; if (!isp(a[1] + 2)){ cout << "0\n2 " << a[1] << " " << a[2] << "\n"; pos = 3; }else if (!isp(a[1] + 4)){ cout << "0\n3 " << a[1] << " " << a[2] << " " << a[3] << "\n"; pos = 4; }else if (!isp(a[1] + 6)){ cout << (k == n / 2) << "\n4 " << a[1] << " " << a[2] << " " << a[3] << " " << a[4] << "\n"; pos = 5; } while (cnt < k - 1){ cout << "2 " << a[pos] << " " << a[pos + 1] << "\n"; pos += 2; ++cnt; } cout << n - pos + 1 << " "; for (int i = pos; i <= n; i++) cout << a[i] << " "; cout << "\n"; }else if (n - cnt == 3){ reverse(a + 1, a + 1 + n); // reverse(a + 1, a + 4); int pos, cnt = 1; if (!isp(a[1] + 2)){ cout << "0\n2 " << a[1] << " " << a[4] << "\n"; pos = 5; }else if (!isp(a[1] + 4)){ cout << "0\n3 " << a[1] << " " << a[4] << " " << a[5] << "\n"; pos = 6; }else if (!isp(a[1] + 6)){ cout << "0\n3 3 3 3\n"; pos = 4; while (cnt < k - 1){ cout << "2 " << a[pos] << " " << a[pos + 1] << "\n"; pos += 2; ++cnt; } cout << n - pos + 1 << " "; for (int i = pos; i <= n; i++) cout << a[i] << " "; cout << "\n"; continue; } while (cnt < k - 1){ cout << "2 " << a[pos] << " " << a[pos + 1] << "\n"; pos += 2; ++cnt; } cout << n - pos + 3 << " "; cout << a[2] << " " << a[3] << " "; for (int i = pos; i <= n; i++) cout << a[i] << " "; cout << "\n"; } }Subtask7
其实和 为奇数会差不多,略难一些。
有偶数个是好做的。 和 分,奇素数和奇素数分。
有奇数个的时候要特判 ,这种情况直接找有没有一个奇素数加上 是合数,有就和 配掉,奇异序列个数为 ;没有就随便拉一个配,个数为 。
剩下的情况还是和上面一样讨论。唯一的区别在于只有一个奇素数 的时候由于 ,我们多了两个 ,可以把 配掉了。这种情况没有奇异序列了。
这里只给出偶数个 和 的代码:
if (!(cnt & 1)){ cout << "0\n"; for (int i = 1; i <= 2 * k - 2; i += 2) cout << "2 " << a[i] << " " << a[i + 1] << "\n"; vector<int> tmp; tmp.clear(); for (int i = 2 * k - 1; i <= n; i++) tmp.emplace_back(i); cout << tmp.size() << " "; for (int i = 2 * k - 1; i <= n; i++) cout << a[i] << " "; cout <<"\n"; }else if (k == n / 2){ bool chk = 1; for (int i = 1; i <= n; i++) if ((a[i] & 1) && !isp(a[i] + 2)){ chk = 0; swap(a[i], a[1]); break; } cout << chk << "\n"; sort(a + 2, a + 1 + n); for (int i = 1; i <= n; i += 2) cout << "2 " << a[i] << " " << a[i + 1] << "\n"; }完整代码
#include<bits/stdc++.h> using namespace std; int t, n, k, a[100005], flg[100005], maimai, tt; vector<int> ans[100005], tmp[105]; long long p[] = {0, 2, 3, 5, 7, 11, 13, 17, 19}; int mn[2005], fnd, buk[5]; typedef long long ll; ll slowtm(ll x, ll k, ll m){ return (__int128)x * k % m; } ll qpow(ll x, ll k, ll m){ ll ans = 1; while(k){ if (k & 1) ans = slowtm(ans, x, m); x = slowtm(x, x, m); k >>= 1; } return ans; } bool Miller_Rabin(ll n, ll a){ ll vp = n - 1, r = 0, pan; while (!(vp & 1)) r++, vp >>= 1; pan = qpow(a, vp, n); if (pan == 1) return 1; for (int i = 0; i < r; i++){ if (pan == n - 1) return 1; pan = slowtm(pan, pan, n); } return 0; } bool isp(ll n){ if (n < 2) return 0; for (int i = 1; i <= 8; i++){ if (n == p[i]) return 1; if (n % p[i] == 0) return 0; if (!Miller_Rabin(n, p[i])) return 0; } return 1; } void dfs(int S, int now, int dep){ if (S == (1 << n) - 1 && dep != k + 1) return; if (now >= mn[S]) return; if (S == (1 << n) - 1){ for (int i = 1; i <= k; i++) ans[i] = tmp[i]; } mn[S] = now; if (dep >= k + 1) return; for (int T = 1; T < (1 << n); T++){ if (S & T) continue; long long sum = 0; for (int i = 1; i <= n; i++) if (T & (1 << i - 1)){ sum += a[i]; tmp[dep].emplace_back(a[i]); } dfs(S | T, now + isp(sum), dep + 1); tmp[dep].clear(); } } int main(){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin >> t; tt = t; while (t--){ cin >> n >> k; ll sum = 0; maimai = INT_MAX; for (int i = 1; i <= n; i++){ cin >> a[i]; maimai = min(maimai, a[i]); } if (k == 1){ for (int i = 1; i <= n; i++) sum += a[i]; if (isp(sum)){ cout << "1\n" << n << " "; for (int i = 1; i <= n; i++) cout << a[i] << " "; cout << "\n"; }else{ cout << "0\n" << n << " "; for (int i = 1; i <= n; i++) cout << a[i] << " "; cout << "\n"; } }else if (n <= 10 && tt <= 20 || n <= 5){ memset(mn, 0x3f, sizeof mn); fnd = 0; dfs(0, 0, 1); cout << mn[(1 << n) - 1] << "\n"; for (int i = 1; i <= k; i++){ cout << ans[i].size() << " "; for (auto u : ans[i]) cout << u << " "; cout << "\n"; ans[i].clear(); } }else if (!(n & 1)){ if (maimai > 2){ if (k <= n / 2){ cout << "0\n"; for (int i = 1; i <= k - 1; i++) cout << "2 " << a[i * 2 - 1] << " " << a[i * 2] << "\n"; cout << n - 2 * (k - 1) << " "; for (int i = (k - 1) * 2 + 1; i <= n; i++) cout << a[i] << " "; cout << "\n"; }else{ cout << 2 * k - n << "\n"; for (int i = 1; i <= 2 * k - n; i++) cout << "1 " << a[i] << "\n"; for (int i = 2 * k - n + 1; i <= n; i += 2) cout << "2 " << a[i] << " " << a[i + 1] << "\n"; } }else{ if (k <= n / 2){ int cnt = 0; for (int i = 1; i <= n; i++){ if (a[i] == 2) ++cnt; else break; } if (!(cnt & 1)){ cout << "0\n"; for (int i = 1; i <= 2 * k - 2; i += 2) cout << "2 " << a[i] << " " << a[i + 1] << "\n"; vector<int> tmp; tmp.clear(); for (int i = 2 * k - 1; i <= n; i++) tmp.emplace_back(i); cout << tmp.size() << " "; for (int i = 2 * k - 1; i <= n; i++) cout << a[i] << " "; cout <<"\n"; }else if (k == n / 2){ bool chk = 1; for (int i = 1; i <= n; i++) if ((a[i] & 1) && !isp(a[i] + 2)){ chk = 0; swap(a[i], a[1]); break; } cout << chk << "\n"; sort(a + 2, a + 1 + n); for (int i = 1; i <= n; i += 2) cout << "2 " << a[i] << " " << a[i + 1] << "\n"; }else if (n - cnt > 3){ cout << "0\n"; memset(buk, 0, sizeof buk); for (int i = 1; i <= n; i++) if (a[i] != 2) buk[a[i] % 3]++; for (int i = 1; i <= n; i++) flg[i] = 0; if (buk[0] >= 3){ cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 0; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 0){ cout << a[i] << " "; flg[i] = 1; ++cnt; ++tot; if (cnt == 3) break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ if (p == 1 && a[i] == 2 && a[i + 1] != 2){ continue; } ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } cout << "\n"; }else if (buk[1] >= 3){ cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 0; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 1){ cout << a[i] << " "; flg[i] = 1; ++cnt; ++tot; if (cnt == 3) break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ if (p == 1 && a[i] == 2 && a[i + 1] != 2){ continue; } ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } }else if (buk[2] >= 3){ cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 0; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 2 && a[i] != 2){ cout << a[i] << " "; flg[i] = 1; ++cnt; ++tot; if (cnt == 3) break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ if (p == 1 && a[i] == 2 && a[i + 1] != 2){ continue; } ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } }else{ reverse(a + 1, a + 1 + n); cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 3; int p1, p2, p3; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 0){ p1 = i; flg[i] = 1; cout << a[i] << " "; break; } } for (int i = 1; i <= n; i++){ if (a[i] % 3 == 1){ p2 = i; flg[i] = 1; cout << a[i] << " "; break; } }for (int i = 1; i <= n; i++){ if (a[i] % 3 == 2){ p3 = i; flg[i] = 1; cout << a[i] << " "; break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ if (p == 1 && a[i] == 2 && a[i + 1] != 2){ continue; } ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } } }else if (n - cnt == 1){ reverse(a + 1, a + 1 + n); int pos, cnt = 1; if (!isp(a[1] + 2)){ cout << "0\n2 " << a[1] << " " << a[2] << "\n"; pos = 3; }else if (!isp(a[1] + 4)){ cout << "0\n3 " << a[1] << " " << a[2] << " " << a[3] << "\n"; pos = 4; }else if (!isp(a[1] + 6)){ cout << "0\n4 " << a[1] << " " << a[2] << " " << a[3] << " " << a[4] << "\n"; pos = 5; } while (cnt < k - 1){ cout << "2 " << a[pos] << " " << a[pos + 1] << "\n"; pos += 2; ++cnt; } cout << n - pos + 1 << " "; for (int i = pos; i <= n; i++) cout << a[i] << " "; cout << "\n"; }else if (n - cnt == 3){ reverse(a + 1, a + 1 + n); // reverse(a + 1, a + 4); int pos, cnt = 1; if (!isp(a[1] + 2)){ cout << "0\n2 " << a[1] << " " << a[4] << "\n"; pos = 5; }else if (!isp(a[1] + 4)){ cout << "0\n3 " << a[1] << " " << a[4] << " " << a[5] << "\n"; pos = 6; }else if (!isp(a[1] + 6)){ cout << "0\n3 3 3 3\n"; pos = 4; while (cnt < k - 1){ cout << "2 " << a[pos] << " " << a[pos + 1] << "\n"; pos += 2; ++cnt; } cout << n - pos + 1 << " "; for (int i = pos; i <= n; i++) cout << a[i] << " "; cout << "\n"; continue; } while (cnt < k - 1){ cout << "2 " << a[pos] << " " << a[pos + 1] << "\n"; pos += 2; ++cnt; } cout << n - pos + 3 << " "; cout << a[2] << " " << a[3] << " "; for (int i = pos; i <= n; i++) cout << a[i] << " "; cout << "\n"; } }else{ int cnt = 0; for (int i = 1; i <= n; i++){ if (a[i] == 2) ++cnt; else break; } for (int i = 1; i <= n; i++) flg[i] = 0; cout << 2 * k - n << "\n"; if (cnt & 1) cout << "1 2\n"; int qwq = (n - k); for (int i = 1 + (cnt & 1); i <= 2 * qwq + (cnt & 1); i += 2) cout << "2 " << a[i] << " " << a[i + 1] << "\n"; for (int i = 2 * qwq + (cnt & 1) + 1; i <= n; i++) cout << "1 " << a[i] << "\n"; } } }else{ if (maimai > 2){ if (k <= n / 2){ cout << "0\n"; memset(buk, 0, sizeof buk); for (int i = 1; i <= n; i++) buk[a[i] % 3]++; for (int i = 1; i <= n; i++) flg[i] = 0; if (buk[0] >= 3){ cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 0; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 0){ cout << a[i] << " "; flg[i] = 1; ++cnt; ++tot; if (cnt == 3) break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } cout << "\n"; }else if (buk[1] >= 3){ cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 0; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 1){ cout << a[i] << " "; flg[i] = 1; ++cnt; ++tot; if (cnt == 3) break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } }else{ cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 0; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 2){ cout << a[i] << " "; flg[i] = 1; ++cnt; ++tot; if (cnt == 3) break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } } }else{ cout << 2 * k - n << "\n"; for (int i = 1; i <= 2 * k - n; i++) cout << "1 " << a[i] << "\n"; for (int i = 2 * k - n + 1; i <= n; i += 2) cout << "2 " << a[i] << " " << a[i + 1] << "\n"; } }else{ if (k <= n / 2){ int cnt = 0; for (int i = 1; i <= n; i++){ if (a[i] == 2) ++cnt; else break; } if (cnt & 1){ cout << "0\n"; if (k == 2){ cout << "3 " << a[1] << " " << a[2] << " " << a[3] << "\n"; cout << n - 3 << " "; for (int i = 4; i <= n; i++) cout << a[i] << " "; cout << "\n"; }else{ cout << "3 " << a[1] << " " << a[2] << " " << a[3] << "\n"; int pos = 4, js = 1; while (1){ if (js == k - 1) break; cout << "2 " << a[pos] << " " << a[pos + 1] << "\n"; pos += 2; ++js; } cout << (n - pos + 1) << " "; for (int i = pos; i <= n; i++) cout << a[i] << " "; cout << "\n"; } }else{ if (n - cnt > 3){ cout << "0\n"; memset(buk, 0, sizeof buk); for (int i = 1; i <= n; i++) if (a[i] != 2) buk[a[i] % 3]++; for (int i = 1; i <= n; i++) flg[i] = 0; if (buk[0] >= 3){ cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 0; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 0){ cout << a[i] << " "; flg[i] = 1; ++cnt; ++tot; if (cnt == 3) break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } cout << "\n"; }else if (buk[1] >= 3){ cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 0; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 1){ cout << a[i] << " "; flg[i] = 1; ++cnt; ++tot; if (cnt == 3) break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } }else if (buk[2] >= 3){ cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 0; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 2 && a[i] != 2){ cout << a[i] << " "; flg[i] = 1; ++cnt; ++tot; if (cnt == 3) break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } }else{ reverse(a + 1, a + 1 + n); cout << "3 "; int cnt = 0, p = 1, js = 1, tot = 3; int p1, p2, p3; for (int i = 1; i <= n; i++){ if (a[i] % 3 == 0){ p1 = i; flg[i] = 1; cout << a[i] << " "; break; } } for (int i = 1; i <= n; i++){ if (a[i] % 3 == 1){ p2 = i; flg[i] = 1; cout << a[i] << " "; break; } }for (int i = 1; i <= n; i++){ if (a[i] % 3 == 2){ p3 = i; flg[i] = 1; cout << a[i] << " "; break; } } cout << "\n"; if (js != k - 1){ for (int i = 1; i <= n; i++){ if (!flg[i]){ ++tot; if (p == 1) cout << "2 " << a[i] << " "; else cout << a[i] << "\n"; p ^= 1; flg[i] = 1; if (!p) js++; else if (js == k - 1) break; } } } cout << n - tot << " "; for (int i = 1; i <= n; i++){ if (!flg[i]) cout << a[i] << " "; } } }else if (n - cnt == 1){ reverse(a + 1, a + 1 + n); int pos, cnt = 1; if (!isp(a[1] + 2)){ cout << "0\n2 " << a[1] << " " << a[2] << "\n"; pos = 3; }else if (!isp(a[1] + 4)){ cout << "0\n3 " << a[1] << " " << a[2] << " " << a[3] << "\n"; pos = 4; }else if (!isp(a[1] + 6)){ cout << (k == n / 2) << "\n4 " << a[1] << " " << a[2] << " " << a[3] << " " << a[4] << "\n"; pos = 5; } while (cnt < k - 1){ cout << "2 " << a[pos] << " " << a[pos + 1] << "\n"; pos += 2; ++cnt; } cout << n - pos + 1 << " "; for (int i = pos; i <= n; i++) cout << a[i] << " "; cout << "\n"; }else if (n - cnt == 3){ reverse(a + 1, a + 1 + n); // reverse(a + 1, a + 4); int pos, cnt = 1; if (!isp(a[1] + 2)){ cout << "0\n2 " << a[1] << " " << a[4] << "\n"; pos = 5; }else if (!isp(a[1] + 4)){ cout << "0\n3 " << a[1] << " " << a[4] << " " << a[5] << "\n"; pos = 6; }else if (!isp(a[1] + 6)){ cout << "0\n3 3 3 3\n"; pos = 4; while (cnt < k - 1){ cout << "2 " << a[pos] << " " << a[pos + 1] << "\n"; pos += 2; ++cnt; } cout << n - pos + 1 << " "; for (int i = pos; i <= n; i++) cout << a[i] << " "; cout << "\n"; continue; } while (cnt < k - 1){ cout << "2 " << a[pos] << " " << a[pos + 1] << "\n"; pos += 2; ++cnt; } cout << n - pos + 3 << " "; cout << a[2] << " " << a[3] << " "; for (int i = pos; i <= n; i++) cout << a[i] << " "; cout << "\n"; } } }else{ int cnt = 0; for (int i = 1; i <= n; i++){ if (a[i] == 2) ++cnt; else break; } for (int i = 1; i <= n; i++) flg[i] = 0; cout << 2 * k - n << "\n"; if (cnt & 1) cout << "1 2\n"; int qwq = (n - k); for (int i = 1 + (cnt & 1); i <= 2 * qwq + (cnt & 1); i += 2) cout << "2 " << a[i] << " " << a[i + 1] << "\n"; for (int i = 2 * qwq + (cnt & 1) + 1; i <= n; i++) cout << "1 " << a[i] << "\n"; } } } } return 0; }结语 做完这道题的感想
萌新时期,总会觉得过掉一道黑题是十分遥远的,写掉一个码量巨大的题是永远做不到的。
但是,真正花时间下去,用最朴素的热爱钻研出一个题,经过一番鏖战做完之后,才发现,不过如此。
难吗?难。但是不累。因为心中的热爱在驱动。或许写的时候会无数次破防,无数次质疑自己,但是,在 Accepted 跳出来的那一瞬间,就会意识到,一切都是值得的。静下心来,就能够一次次取得突破。
“蚓无爪牙之利,筋骨之强,上食埃土,下饮黄泉,用心一也;蟹六跪而二螯,非蛇鳝之穴无所寄托者,用心躁也。”
2025 赛季已经开始,愿我们都能在这段时间内静下心来,在每一场比赛中取得令自己满意的成绩,不给 OI 之旅留下遗憾。
- 1
信息
- ID
- 10196
- 时间
- 1500ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 7
- 已通过
- 1
- 上传者