第十三次CCF計算機軟體能力認證 題解(臨時版)
阿新 • • 發佈:2019-01-01
前言
剛做完= =第五題寫炸了
先大概講講我的思路,有機會我會寫個完整的題解(估計不可能啦,忙的要死)
這些程式碼都是我比賽時候寫的,不保證正確性
第一題
水題,記錄最後一次的得分即可
#include <cstdio> using namespace std; int main() { int ans = 0, base = 1, x; while (true) { scanf("%d", &x); if (x == 0) { printf("%d\n", ans); break; } else if (x == 1) base = 1; else if (base == 1) base = 2; else base += 2; ans += base; } return 0; }
第二題
考慮到兩個球相碰只會變方向,所以模擬球的執行即可
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int a[105], d[105], vis[1005]; int main() { int n, L, t; scanf("%d%d%d", &n, &L, &t); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); d[i] = 1; } for (int i = 1; i <= t; i++) { memset(vis, -1, sizeof(vis)); for (int j = 0; j < n; j++) { a[j] += d[j]; if (vis[a[j]] != -1) swap(d[j], d[vis[a[j]]]); else vis[a[j]] = j; if (a[j] == 0) d[j] = 1; if (a[j] == L) d[j] = -1; } } for (int i = 0; i < n; i++) { printf("%d%c", a[i], i == n - 1 ? '\n' : ' '); } return 0; }
第三題
按照題意理解,會發現只需要考慮三種匹配的情況即可。
#include <iostream> #include <string> #include <vector> using namespace std; string S, R, rule[105], name[105], str; vector<string> ans; int L[105]; int main() { int n, m, len, rule_pos, str_pos; bool error, flag; cin >> n >> m; for (int i = 0; i < n; i++) { cin >> rule[i] >> name[i]; L[i] = rule[i].length(); } for (int i = 0; i < m; i++) { flag = false; cin >> str; len = str.length(); for (int j = 0; j < n; j++) { //cout << "Here is rule NO." << j << endl; ans.clear(); rule_pos = 0, str_pos = 0, error = false; while (str_pos < len && rule_pos < L[j]) { //cout << "At str_pos = " << str_pos << " , rule_pos = " << rule_pos << endl; if (rule[j][rule_pos] == '<') { rule_pos++; R.clear(); while (rule[j][rule_pos] != '>') { R += rule[j][rule_pos]; rule_pos++; } rule_pos++; if (R == "int") { S.clear(); while (true) { if (str_pos == len) { if (S.length() == 0) { error = true; } break; } if (str[str_pos] == '/') { if (S.length() == 0) { error = true; } break; } else if (str[str_pos] >= '0' && str[str_pos] <= '9') { S += str[str_pos]; str_pos++; } else { error = true; break; } } if (error) break; if (S.find_first_not_of('0') == string::npos) ans.push_back("0"); else { S = S.substr(S.find_first_not_of('0')); ans.push_back(S); } } else if (R == "str") { S.clear(); while (true) { if (str_pos == len) { if (S.length() == 0) { error = true; } break; } if (str[str_pos] == '/') { if (S.length() == 0) { error = true; } break; } else if (str[str_pos] >= '0' && str[str_pos] <= '9') { S += str[str_pos]; str_pos++; } else if (str[str_pos] == '-') { S += str[str_pos]; str_pos++; } else if (str[str_pos] == '_') { S += str[str_pos]; str_pos++; } else if (str[str_pos] == '.') { S += str[str_pos]; str_pos++; } else if (str[str_pos] >= 'a' && str[str_pos] <= 'z') { S += str[str_pos]; str_pos++; } else if (str[str_pos] >= 'A' && str[str_pos] <= 'Z') { S += str[str_pos]; str_pos++; } else { error = true; break; } } if (error) break; ans.push_back(S); } else { S.clear(); while (true) { if (str_pos == len) { if (S.length() == 0) { error = true; } break; } if (str[str_pos] == '/') { S += str[str_pos]; str_pos++; } else if (str[str_pos] >= '0' && str[str_pos] <= '9') { S += str[str_pos]; str_pos++; } else if (str[str_pos] == '-') { S += str[str_pos]; str_pos++; } else if (str[str_pos] == '_') { S += str[str_pos]; str_pos++; } else if (str[str_pos] == '.') { S += str[str_pos]; str_pos++; } else if (str[str_pos] >= 'a' && str[str_pos] <= 'z') { S += str[str_pos]; str_pos++; } else if (str[str_pos] >= 'A' && str[str_pos] <= 'Z') { S += str[str_pos]; str_pos++; } else { error = true; break; } } if (error) break; ans.push_back(S); } } else { if (rule[j][rule_pos] != str[str_pos]) { error = true; break; } str_pos++; rule_pos++; } } if (str_pos < len || rule_pos < L[j]) error = true; if (!error) { cout << name[j]; for (int m = 0; m < ans.size(); m++) cout << " " << ans[m]; cout << endl; flag = true; break; } } if (!flag) cout << "404" << endl; } return 0; }
第四題
下棋的情況最多9!種,暴力列舉所有情況即可
#include <cstdio>
#include <algorithm>
using namespace std;
int mp[5][5];
int judge() {
int cnt = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (mp[i][j] == 0) cnt++;
}
}
for (int d = 1; d <= 2; d++) {
for (int i = 0; i < 3; i++) {
bool flag = true;
for (int j = 0; j < 3; j++) {
flag = (flag && (mp[i][j] == d));
}
if (flag) {
if (d == 1) return cnt + 1;
else return -cnt - 1;
}
}
}
for (int d = 1; d <= 2; d++) {
for (int j = 0; j < 3; j++) {
bool flag = true;
for (int i = 0; i < 3; i++) {
flag = (flag && (mp[i][j] == d));
}
if (flag) {
if (d == 1) return cnt + 1;
else return -cnt - 1;
}
}
}
for (int d = 1; d <= 2; d++) {
bool flag = true;
for (int i = 0; i < 3; i++) {
flag = (flag && (mp[i][i] == d));
}
if (flag) {
if (d == 1) return cnt + 1;
else return -cnt - 1;
}
}
for (int d = 1; d <= 2; d++) {
bool flag = true;
for (int i = 0; i < 3; i++) {
flag = (flag && (mp[i][2 - i] == d));
}
if (flag) {
if (d == 1) return cnt + 1;
else return -cnt - 1;
}
}
return 0;
}
int dfs(int cnt, bool flag) {
int ans;
if (flag) ans = -10;
else ans = 10;
int X = judge();
if (X != 0) return X;
if (cnt == 9) return X;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (mp[i][j] == 0) {
if (flag) mp[i][j] = 1;
else mp[i][j] = 2;
if (flag) ans = max(ans, dfs(cnt + 1, !flag));
else ans = min(ans, dfs(cnt + 1, !flag));
mp[i][j] = 0;
}
}
}
return ans;
}
int main() {
int T, cnt;
scanf("%d", &T);
while (T--) {
cnt = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
scanf("%d", &mp[i][j]);
if (mp[i][j] != 0) cnt++;
}
}
printf("%d\n", dfs(cnt, true));
}
return 0;
}
第五題
考慮到每次操作只是對一條鏈加一個值,所以我們可以預處理出每個節點對答案的貢獻倍數,然後每次記錄答案,那麼我們就不需要更新節點值,而是直接在答案上加。
我寫的是n^2預處理貢獻,mlognlogn進行計算答案,可惜寫炸了。。。
貌似100%的通過需要用樹分治預處理貢獻
以下的程式碼是寫炸的,等到cspro把題掛出來了我再嘗試改正吧= =||
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define ms(x) memset(x, 0, sizeof(x))
typedef vector<int> vi;
typedef long long ll;
const ll MOD = 1e9 + 7;
const int MAX_N = 2e3 + 5;
vi mp[MAX_N];
int Size[MAX_N], pre[MAX_N], depth[MAX_N], Top[MAX_N], ID[MAX_N], son[MAX_N], tot, n, lmtL, lmtR;
ll w[MAX_N], a[MAX_N];
//map<int, int> num[MAX_N];
struct Segment_Tree {
struct Node {
ll seg;
} T[MAX_N << 2];
void push_up(int rt) {
T[rt].seg = (T[rt << 1].seg + T[rt << 1 | 1].seg) % MOD;
}
void Build(int l, int r, int rt) {
T[rt].seg = 0;
if (l == r) {
T[rt].seg = 0;
return;
}
int m = (l + r) >> 1;
Build(lson), Build(rson), push_up(rt);
}
void Update(int pos, ll c, int l, int r, int rt) {
if (l == r) {
T[rt].seg = c;
return;
}
int m = (l + r) >> 1;
if (pos <= m) Update(pos, c, lson);
if (pos > m) Update(pos, c, rson);
push_up(rt);
}
ll Query(int L, int R, int l, int r, int rt) {
if (L > R) return -1;
if (L <= l && r <= R) return T[rt].seg;
int m = (l + r) >> 1;
ll ret = 0;
if (L <= m) ret = (ret + Query(L, R, lson)) % MOD;
if (m < R) ret = (ret + Query(L, R, rson)) % MOD;
return ret;
}
} ST;
void init_HLD(int x, int dad) {
Size[x] = 1, pre[x] = dad;
for (int i = 0; i < mp[x].size(); i++) {
int y = mp[x][i];
if (y == dad) continue;
depth[y] = depth[x] + 1;
init_HLD(y, x);
Size[x] += Size[y];
if (Size[y] > Size[son[x]]) son[x] = y;
}
}
void HLD(int x, int Tp) {
Top[x] = Tp, tot++;
ID[x] = tot;
ST.Update(ID[x], w[x], 1, n, 1);
if (son[x] > 0) HLD(son[x], Tp);
for (int i = 0; i < mp[x].size(); i++) {
int y = mp[x][i];
if (y == pre[x]) continue;
if (y == son[x]) continue;
HLD(y, y);
}
}
ll Query(int x, int y) {
int X = Top[x], Y = Top[y];
ll ans = 0;
while (X != Y) {
if (depth[X] < depth[Y]) swap(X, Y), swap(x, y);
ans = (ans + ST.Query(ID[x], ID[y], 1, n, 1)) % MOD;
x = pre[X], X = Top[x];
}
if (depth[x] > depth[y]) swap(x, y);
ans = (ans + ST.Query(ID[x], ID[y], 1, n, 1)) % MOD;
//printf("Query(%d, %d) = %lld\n", x, y, ans);
return ans;
}
void HLD_INIT(int root) {
ms(son), tot = 0, depth[root] = 0;
init_HLD(root, 0);
HLD(root, root);
}
ll dfs(int x, int dad, int d) {
ll ans = 0;
if (d >= lmtL && d <= lmtR) ans++;
for (int i = 0; i < mp[x].size(); i++) {
int y = mp[x][i];
if (y == dad) continue;
ans = (ans + dfs(y, x, d + 1)) % MOD;
}
w[x] = (ans + w[x]) % MOD;
return ans;
}
int main() {
int T, m, x, u, v;
ll ans, d;
scanf("%d", &T);
while (T--) {
ms(w), ms(a), ans = 0;
scanf("%d%d%d%d", &n, &m, &lmtL, &lmtR);
for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
for (int i = 2; i <= n; i++) {
scanf("%d", &x);
mp[x].push_back(i);
mp[i].push_back(x);
}
for (int i = 1; i <= n; i++) {
dfs(i, 0, 1);
ans = (ans + w[i] * a[i] % MOD) % MOD;
}
for (int j = 1; j <= n; j++) w[j] /= 2;
ST.Build(1, n, 1);
HLD_INIT(1);
//printf("ans = %lld\n", ans);
while (m--) {
scanf("%d%d%lld", &u, &v, &d);
ans = (ans + Query(u, v) * d % MOD) % MOD;
printf("%lld\n", ans);
}
}
return 0;
}