邮寄
开场 A 写了 70,然后写 C。
C 大样例过了。
然后 D 写了 30 走人。
B 在知晓题意后,过了样例。
然后撤退了。
70+0+40+50=160。
A 光
我们先预处理出 \(a, b, c, d \le 14\) 的答案(待会儿要考)。
然后,有一种贪心思路:
每次找到亮度需求最多的地方,加上 \(4\) 点亮度,重新计算贡献。
当 \(a, b, c, d \le 14\),直接输出(如果你不知道为什么,那么等待你的将会是 WA 20pts)。
#include <bits/stdc++.h>
using namespace std;
int a, b, c, d, as[50][50][50][50], ans;
int check(int x, int y, int z, int w, int ra, int rb, int rc, int rd) {
if(ra + rb / 2 + rc / 2 + rd / 4 < x) {
return 0;
}
if(rb + ra / 2 + rd / 2 + rc / 4 < y) {
return 0;
}
if(rc + ra / 2 + rd / 2 + rb / 4 < z) {
return 0;
}
if(rd + rb / 2 + rc / 2 + ra / 4 < w) {
return 0;
}
return 1;
}
int cal(int a, int b, int c, int d) {
int ans = 155555;
for(int i = 0; i <= a && i <= ans; i++) {
for(int j = 0; j <= b && i + j <= ans; j++) {
for(int k = 0; k <= c && i + j + k <= ans; k++) {
for(int l = 0; l <= d && i + j + k + l <= ans; l++) {
if(check(a, b, c, d, i, j, k, l)) {
ans = min(ans, i + j + k + l);
}
}
}
}
}
return ans;
}
int main() {
freopen("light.in", "r", stdin);
freopen("light.out", "w", stdout);
for(int i = 0; i <= 14; i++) {
for(int j = 0; j <= 14; j++) {
for(int k = 0; k <= 14; k++) {
for(int l = 0; l <= 14; l++) {
as[i][j][k][l] = cal(i, j, k, l);
}
}
}
}
cin >> a >> b >> c >> d;
for(; a >= 15 || b >= 15 || c >= 15 || d >= 15; ) {
int tmp = max({a, b, c, d});
ans += 4;
if(a == tmp) {
a -= 4, b -= 2, c -= 2, d -= 1;
}else {
if(b == tmp) {
b -= 4, a -= 2, d -= 2, c -= 1;
}else {
if(c == tmp) {
c -= 4, a -= 2, d -= 2, b -= 1;
}else {
d -= 4, b -= 2, c -= 2, a -= 1;
}
}
}
a = max(a, 0), b = max(b, 0), c = max(c, 0), d = max(d, 0);
}
cout << ans + as[a][b][c][d] << '\n';
return 0;
}
B 爬
讲简单点,就是子集异或和之和。
可以拆位,一位一位统计贡献。
#include <bits/stdc++.h>
#define int ll
using namespace std;
using ll = long long;
const int kMod = int(1e9) + 7;
int n, arr[100010], sum, f;
vector<int> ch[100010];
int qpow(int x, int y) {
int rs = 1;
for(; y; y >>= 1) {
if(y & 1) {
rs = rs * x % kMod;
}
x = x * x % kMod;
}
return rs;
}
int cal(const vector<int> &x, int c, bool f = 0) {
int ans = 0;
for(int i = 30; i >= 0; i--) {
int c1 = 0, c0 = 0;
for(auto j : x) {
c1 += ((j >> i) & 1);
c0 += !((j >> i) & 1);
}
if(!((c >> i) & 1)) {
if(c1) {
ans = (ans + (qpow(2, c0) * qpow(2, c1 - 1) - (!f) * c1 + kMod) % kMod * qpow(2, i)) % kMod;
}
}else {
ans = (ans + (qpow(2, c0) * (c1? qpow(2, c1 - 1) : 1) - 1 + kMod) % kMod * qpow(2, i)) % kMod;
}
}
return ans;
}
void DFS(int x) {
vector<int> s;
if(x != 1) {
s.push_back(arr[x]);
}
for(auto i : ch[x]) {
DFS(i);
s.push_back(arr[i]);
}
if(x != 1) {
//cout << x << ' ' << cal(s, 0) << '\n';
sum = (sum + cal(s, 0) * qpow(2, n - 1 - s.size())) % kMod;
}else {
//cout << x << ' ' << cal(s, arr[x], 1) << '\n';
sum = (sum + cal(s, arr[x], 1) * qpow(2, n - 1 - s.size())) % kMod;
}
}
signed main() {
freopen("climb.in", "r", stdin);
freopen("climb.out", "w", stdout);
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> arr[i];
}
for(int i = 2; i <= n; i++) {
cin >> f;
ch[f].push_back(i);
}
DFS(1);
cout << sum << '\n';
return 0;
}
//Off-Topic: It should be "crawl"
C 字符串
贪心,先贪断点的,然后贪连续的。
#include <bits/stdc++.h>
using namespace std;
int t, n, m, a, b, c, ans, cnt;
int main() {
freopen("string.in", "r", stdin);
freopen("string.out", "w", stdout);
for(cin >> t; t--;) {
cin >> n >> m >> a >> b >> c;
ans = (n - 1) / a + (m - 1) / b + 2, cnt = min(n, m / c);
for(int i = 1; i <= cnt; i++) {
int val = 2 * i;
if(c > b) {
val += (c - 1) / b * i;
}
if(n - i > 0) {
val += 1 + (n - i - 1) / a;
}
if(m - c * i > 0) {
val++;
int rst = m - c * i - 1;
if(c <= b) {
int nv = min(i, rst / (b + 1 - c));
val += nv, rst -= nv * (b + 1 - c);
}else {
int nv = min(i, rst / (b - (c - 1) % b));
val += nv, rst -= nv * (b - (c - 1) % b);
}
val += rst / b;
}
ans = max(ans, val);
}
cout << ans << '\n';
}
return 0;
}
标签:kMod,return,qpow,int,ans,c1,9.0
From: https://www.cnblogs.com/leavenothingafterblog/p/18440299/speedrunv9