首页 > 代码库 > Weekly Challenges - Week 11
Weekly Challenges - Week 11
一拖再拖,忍无可忍,自己懒的没救了。
一周前就结束的比赛,到现在才想起来补。
最后一题貌似又遇到了splay。。。还是不会!!!shit
题目链接
A题--快速幂
1 #include <cmath> 2 #include <cstdio> 3 #include <vector> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 const int MOD = 1e9 + 7; 9 10 int mod_pow(int a, int b) {11 int res = 1;12 while (b) {13 if (b & 1) res = (res * (long long)a) % MOD;14 a = (a * (long long)a) % MOD;15 b >>= 1;16 }17 return res;18 }19 20 int main() {21 /* Enter your code here. Read input from STDIN. Print output to STDOUT */ 22 int T;23 ios::sync_with_stdio(false);24 cin >> T;25 while (T--) {26 int t;27 cin >> t;28 cout << (2 + mod_pow(2, t + 1)) % MOD << endl;29 }30 return 0;31 }
B题
如果说这题的困难之处,那就是要看出来其实这种数的个数很少。所以先把所有的范围之内的数打表出来。
1 #include <cmath> 2 #include <cstdio> 3 #include <vector> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 typedef long long LL; 9 #define rep(i, n) for (int i = (1); i <= (n); i++)10 LL pw10[20];11 const LL MAX_N = (LL)1e18;12 13 int main() {14 pw10[0] = 1LL;15 rep (i, 19) pw10[i] = pw10[i - 1] * 10;16 vector<LL> ans;17 rep (i, 9) ans.push_back(i);18 int cur = 0, cur_len = 2, next = -1;19 while (true) {20 if (next == - 1 && ans[cur] * (cur_len + 1) >= pw10[cur_len]) {21 next = cur;22 }23 LL x = ans[cur] * cur_len;24 if (x >= MAX_N) break;25 if (pw10[cur_len - 1] <= x && x < pw10[cur_len]) {26 ans.push_back(x);27 } else if (x >= pw10[cur_len]) {28 cur = next;29 next = -1;30 cur_len++;31 continue;32 }33 cur++;34 }35 //rep (i, 25) cerr << ans[i] << endl;36 int T;37 cin >> T;38 while (T--) {39 LL A, B;40 cin >> A >> B;41 LL rgt = upper_bound(ans.begin(), ans.end(), B) - ans.begin();42 LL lft = lower_bound(ans.begin(), ans.end(), A) - ans.begin();43 LL res = rgt - lft;44 if (A == 0) res++;45 cout << res << endl;46 }47 48 return 0;49 }
C题
题意:给出N个结点的树,每个结点有一个权值,在树上有一种操作,可以任选一个结点,然后删除以该结点为根的子树。最多执行K次这种操作
使得树上的权值总和最大。
首先,如果按照前序遍历访问每个结点的顺序给结点做标记,那么以某个结点为根的子树中所有结点的标记一定该结点的后面。
dfs时顺便维护一下以每个结点为根的子树中结点的个数tot[i]。
dp[i][j]表示到dfs中第i个遍历的结点为止操作了j次可以获得的最大权值。
这样当到达第i个结点时,dp[i + 1][j] = max(dp[i + 1][j], dp[i][j] + value[i]) //不删除
dp[i + tot[i]][j + 1] = max(dp[i + tot[i]][j + 1], dp[i][j]) //删除
1 #include <cmath> 2 #include <cstdio> 3 #include <vector> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 const int MAX_N = 100050; 9 typedef long long LL;10 const LL INF = (LL)1e19;11 vector<int> G[MAX_N];12 int w[MAX_N], vs[MAX_N], tot[MAX_N], cnt;13 LL dp[MAX_N][205];14 15 void dfs(int u, int fa) {16 int sz = (int)G[u].size();17 vs[++cnt] = u;18 tot[u] = 1;19 if (sz == 1) {20 return ;21 }22 for (int i = 0; i < sz; i++) {23 int v = G[u][i];24 if (v == fa) continue;25 dfs(v, u);26 tot[u] += tot[v];27 }28 }29 30 void read(int &res) {31 res = 0;32 int sign = 1;33 char c = ‘ ‘;34 while (c < ‘0‘ || c > ‘9‘) {35 if (c == ‘-‘) sign = -1;36 c = getchar();37 }38 while (c >= ‘0‘ && c <= ‘9‘) res = (res<<3) + (res<<1) + c - ‘0‘, c = getchar();39 if (sign == -1) res = -res;40 }41 42 int main() {43 ios::sync_with_stdio(false);44 int N, K;45 cin >> N >> K;46 //read(N); read(K);47 for (int i = 1; i <= N; i++) cin >> w[i];//read(w[i]);48 for (int i = 1; i < N; i++) {49 int u, v;50 cin >> u >> v;51 //read(u), read(v);52 G[u].push_back(v);53 G[v].push_back(u);54 }55 cnt = 0;56 dfs(1, -1);57 for (int i = 0; i <= K; i++) for (int j = 1; j <= N; j++) dp[j][i] = -INF;58 //for (int i = 0; i <= K; i++) dp[0][i] = 0;59 dp[1][0] = 0;60 for (int i = 1; i <= N; i++) {61 int u = vs[i];62 for (int j = 0; j <= K; j++) if (dp[i][j] != -INF) {63 dp[i + 1][j] = max(dp[i + 1][j], dp[i][j] + w[u]);64 if (j < K)65 dp[i + tot[u]][j + 1] = max(dp[i + tot[u]][j + 1], dp[i][j]);66 }67 }68 LL res = -INF;69 for (int i = 0; i <= K; i++) res = max(res, dp[N + 1][i]);70 cout << res << endl;71 72 return 0;73 }
D题
题意:N种技能,第i种技能有ci个人学会,有T个巫师,每个巫师有两个集合A和B,他可以把一个拥有A集合中的技能的人转移到集合B中的某个技能中去。
问最多可以使多少个技能至少有一个人学会。
增加一个源点和汇点,源点到N种技能连一条容量为ci的边,从N种技能到汇点连一条容量为1的边。
对于每个巫师,从A集合中的技能连一条容量为1的边到该巫师,从该巫师连一条容量为1的边到B集合中的每种技能。
最大流即为答案。。。
1 #include <queue> 2 #include <cmath> 3 #include <cstdio> 4 #include <vector> 5 #include <cstring> 6 #include <iostream> 7 #include <algorithm> 8 using namespace std; 9 10 struct edge { 11 int to, cap, rev; 12 edge() {} 13 edge(int _to, int _cap, int _rev):to(_to), cap(_cap), rev(_rev) {} 14 }; 15 const int INF = 0x3f3f3f3f; 16 const int MAX_V = 250; // ????` 17 vector<edge> G[MAX_V]; // ????? 18 int level[MAX_V]; // ?????????? 19 int iter[MAX_V]; // ???????????????? 20 int Q[MAX_V]; // BFS?? 21 22 void add_edge(int from, int to, int cap) { 23 G[from].push_back(edge(to, cap, G[to].size())); 24 G[to].push_back(edge(from, 0, G[from].size() - 1)); 25 } 26 27 // ????????????????? 28 void bfs(int s) { 29 memset(level, -1, sizeof(level)); 30 int ini = 0, end = 0; 31 Q[end++] = s; 32 level[s] = 0; 33 while (end > ini) { 34 int v = Q[ini++]; 35 for (int i = 0; i < G[v].size(); i++) { 36 edge &e = G[v][i]; 37 if (e.cap > 0 && level[e.to] < 0) { 38 level[e.to] = level[v] + 1; 39 Q[end++] = e.to; 40 } 41 } 42 } 43 } 44 45 // ?????????? 46 int dfs(int v, int t, int f) { 47 if (v == t) return f; 48 for (int &i = iter[v]; i < G[v].size(); i++) { 49 edge &e = G[v][i]; 50 if (e.cap > 0 && level[v] < level[e.to]) { 51 int d = dfs(e.to, t, min(f, e.cap)); 52 if (d > 0) { 53 e.cap -= d; 54 G[e.to][e.rev].cap += d; 55 return d; 56 } 57 } 58 } 59 return 0; 60 } 61 62 // ?????????? 63 int Dinic(int s, int t) { 64 int flow = 0; 65 for (;;) { 66 bfs(s); 67 if (level[t] < 0) return flow; 68 memset(iter, 0, sizeof(iter)); 69 int f; 70 while ((f = dfs(s, t, INF)) > 0) { 71 flow += f; 72 } 73 } 74 } 75 76 int main() { 77 ios_base::sync_with_stdio(false); 78 79 int N, T; 80 cin >> N >> T; 81 int s = 0, t = N + T + 1; 82 83 for (int i = 1; i <= N; i++) { 84 int C; 85 cin >> C; 86 add_edge(s, i, C); 87 add_edge(i, t, 1); 88 } 89 for (int i = 1; i <= T; i++) { 90 int A, B; 91 cin >> A; 92 for (int j = 1; j <= A; j++) { 93 int x; 94 cin >> x; 95 add_edge(x, N + i, 1); 96 } 97 cin >> B; 98 for (int j = 1; j <= B; j++) { 99 int x;100 cin >> x;101 add_edge(N + i, x, 1);102 }103 }104 105 cout << Dinic(s, t) << endl;106 return 0;107 }
1 #include <queue> 2 #include <cmath> 3 #include <cstdio> 4 #include <vector> 5 #include <cstring> 6 #include <iostream> 7 #include <algorithm> 8 using namespace std; 9 10 struct edge { 11 int to, cap, rev; 12 edge() {} 13 edge(int _to, int _cap, int _rev):to(_to), cap(_cap), rev(_rev) {} 14 }; 15 const int INF = 0x3f3f3f3f; 16 const int MAX_V = 250; // ????` 17 vector<edge> G[MAX_V]; // ????? 18 int level[MAX_V]; // ?????????? 19 int iter[MAX_V]; // ???????????????? 20 int Q[MAX_V]; // BFS?? 21 22 void add_edge(int from, int to, int cap) { 23 G[from].push_back(edge(to, cap, G[to].size())); 24 G[to].push_back(edge(from, 0, G[from].size() - 1)); 25 } 26 27 // ????????????????? 28 void bfs(int s) { 29 memset(level, -1, sizeof(level)); 30 int ini = 0, end = 0; 31 Q[end++] = s; 32 level[s] = 0; 33 while (end > ini) { 34 int v = Q[ini++]; 35 for (int i = 0; i < G[v].size(); i++) { 36 edge &e = G[v][i]; 37 if (e.cap > 0 && level[e.to] < 0) { 38 level[e.to] = level[v] + 1; 39 Q[end++] = e.to; 40 } 41 } 42 } 43 } 44 45 // ?????????? 46 int dfs(int v, int t, int f) { 47 if (v == t) return f; 48 for (int &i = iter[v]; i < G[v].size(); i++) { 49 edge &e = G[v][i]; 50 if (e.cap > 0 && level[v] < level[e.to]) { 51 int d = dfs(e.to, t, min(f, e.cap)); 52 if (d > 0) { 53 e.cap -= d; 54 G[e.to][e.rev].cap += d; 55 return d; 56 } 57 } 58 } 59 return 0; 60 } 61 62 // ?????????? 63 int Dinic(int s, int t) { 64 int flow = 0; 65 for (;;) { 66 bfs(s); 67 if (level[t] < 0) return flow; 68 memset(iter, 0, sizeof(iter)); 69 int f; 70 while ((f = dfs(s, t, INF)) > 0) { 71 flow += f; 72 } 73 } 74 } 75 76 int main() { 77 ios_base::sync_with_stdio(false); 78 79 int N, T; 80 cin >> N >> T; 81 int s = 0, t = N + T + 1; 82 83 for (int i = 1; i <= N; i++) { 84 int C; 85 cin >> C; 86 add_edge(s, i, C); 87 add_edge(i, t, 1); 88 } 89 for (int i = 1; i <= T; i++) { 90 int A, B; 91 cin >> A; 92 for (int j = 1; j <= A; j++) { 93 int x; 94 cin >> x; 95 add_edge(x, N + i, 1); 96 } 97 cin >> B; 98 for (int j = 1; j <= B; j++) { 99 int x;100 cin >> x;101 add_edge(N + i, x, 1);102 }103 }104 105 cout << Dinic(s, t) << endl;106 return 0;107 }
E题
Weekly Challenges - Week 11