AtCoder Grand Contest 013 题解
A - Sorted Arrays
贪心,看看不下降和不上升最长能到哪,直接转移过去即可。
1 //waz 2 #include <bits/stdc++.h> 3 4 using namespace std; 5 6 #define mp make_pair 7 #define pb push_back 8 #define fi first 9 #define se second 10 #define ALL(x) (x).begin(), (x).end() 11 #define SZ(x) ((int)((x).size())) 12 13 typedef pair<int, int> PII; 14 typedef vector<int> VI; 15 typedef long long int64; 16 typedef unsigned int uint; 17 typedef unsigned long long uint64; 18 19 #define gi(x) ((x) = F()) 20 #define gii(x, y) (gi(x), gi(y)) 21 #define giii(x, y, z) (gii(x, y), gi(z)) 22 23 int F() 24 { 25 char ch; 26 int x, a; 27 while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-'); 28 if (ch == '-') ch = getchar(), a = -1; 29 else a = 1; 30 x = ch - '0'; 31 while (ch = getchar(), ch >= '0' && ch <= '9') 32 x = (x << 1) + (x << 3) + ch - '0'; 33 return a * x; 34 } 35 36 const int mod = 1e9 + 7; 37 38 int n, a[100010], cnt; 39 40 int main() 41 { 42 gi(n); 43 for (int i = 1; i <= n; ++i) gi(a[i]); 44 for (int i = 1; i <= n; ++i) 45 { 46 int j = i, k = i; 47 while (j < n && a[j + 1] >= a[j]) ++j; 48 while (k < n && a[k + 1] <= a[k]) ++k; 49 i = max(j, k); 50 ++cnt; 51 } 52 printf("%d\n", cnt); 53 return 0; 54 }
B - Hamiltonish Path
随便选一个边,从两头开始dfs到不能走就就好了。
1 //waz 2 #include <bits/stdc++.h> 3 4 using namespace std; 5 6 #define mp make_pair 7 #define pb push_back 8 #define fi first 9 #define se second 10 #define ALL(x) (x).begin(), (x).end() 11 #define SZ(x) ((int)((x).size())) 12 13 typedef pair<int, int> PII; 14 typedef vector<int> VI; 15 typedef long long int64; 16 typedef unsigned int uint; 17 typedef unsigned long long uint64; 18 19 #define gi(x) ((x) = F()) 20 #define gii(x, y) (gi(x), gi(y)) 21 #define giii(x, y, z) (gii(x, y), gi(z)) 22 23 int F() 24 { 25 char ch; 26 int x, a; 27 while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-'); 28 if (ch == '-') ch = getchar(), a = -1; 29 else a = 1; 30 x = ch - '0'; 31 while (ch = getchar(), ch >= '0' && ch <= '9') 32 x = (x << 1) + (x << 3) + ch - '0'; 33 return a * x; 34 } 35 36 const int N = 1e5 + 10; 37 38 int n, m; 39 40 VI edge[N]; 41 42 VI l, r; 43 44 bool vis[N]; 45 46 int main() 47 { 48 gii(n, m); 49 for (int i = 1; i <= m; ++i) 50 { 51 int u, v; 52 gii(u, v); 53 edge[u].pb(v); 54 edge[v].pb(u); 55 if (i == 1) vis[u] = vis[v] = 1, l.pb(u), r.pb(v); 56 } 57 while (1) 58 { 59 int x = -1; 60 for (auto v : edge[l.back()]) 61 if (!vis[v]) x = v; 62 if (x == -1) break; 63 l.pb(x); vis[x] = 1; 64 } 65 while (1) 66 { 67 int x = -1; 68 for (auto v : edge[r.back()]) 69 if (!vis[v]) x = v; 70 if (x == -1) break; 71 r.pb(x); vis[x] = 1; 72 } 73 printf("%d\n", SZ(l) + SZ(r)); 74 reverse(ALL(l)); 75 for (auto x : l) 76 printf("%d ", x); 77 for (auto x : r) 78 printf("%d ", x); 79 return 0; 80 }
C - Ants on a Circle
很明显的套路,蚂蚁的相对位置肯定不变,那么我们算出每个蚂蚁走了多少,最后排序一下,主要是算第一个位置是谁,再统计一下经过了圆多少次就好了。
1 //waz 2 #include <bits/stdc++.h> 3 4 using namespace std; 5 6 #define mp make_pair 7 #define pb push_back 8 #define fi first 9 #define se second 10 #define ALL(x) (x).begin(), (x).end() 11 #define SZ(x) ((int)((x).size())) 12 13 typedef pair<int, int> PII; 14 typedef vector<int> VI; 15 typedef long long int64; 16 typedef unsigned int uint; 17 typedef unsigned long long uint64; 18 19 #define gi(x) ((x) = F()) 20 #define gii(x, y) (gi(x), gi(y)) 21 #define giii(x, y, z) (gii(x, y), gi(z)) 22 23 int F() 24 { 25 char ch; 26 int x, a; 27 while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-'); 28 if (ch == '-') ch = getchar(), a = -1; 29 else a = 1; 30 x = ch - '0'; 31 while (ch = getchar(), ch >= '0' && ch <= '9') 32 x = (x << 1) + (x << 3) + ch - '0'; 33 return a * x; 34 } 35 36 const int N = 1e5 + 10; 37 38 int n, l, t; 39 40 int x[N], w[N]; 41 42 int main() 43 { 44 giii(n, l, t); 45 long long v = 0; 46 for (int i = 1; i <= n; ++i) 47 { 48 gii(x[i], w[i]); 49 if (w[i] == 1) 50 { 51 x[i] += t; 52 v += x[i] / l; 53 x[i] %= l; 54 } 55 else 56 { 57 x[i] -= t; 58 if (x[i] < 0) 59 { 60 v += (x[i] - (l - 1)) / l; 61 } 62 x[i] %= l; 63 if (x[i] < 0) x[i] += l; 64 } 65 } 66 sort(x + 1, x + n + 1); 67 v %= n; 68 if (v < 0) v += n; 69 for (int i = 1; i <= n; ++i) 70 { 71 int j = i + v; 72 if (j > n) j -= n; 73 printf("%d\n", x[j]); 74 } 75 return 0; 76 }
D - Piling Up
直接f[i][j]dp会算重,我们加一维0/1表示是否曾经到达过0,这样子就不会重了。
1 //waz 2 #include <bits/stdc++.h> 3 4 using namespace std; 5 6 #define mp make_pair 7 #define pb push_back 8 #define fi first 9 #define se second 10 #define ALL(x) (x).begin(), (x).end() 11 #define SZ(x) ((int)((x).size())) 12 13 typedef pair<int, int> PII; 14 typedef vector<int> VI; 15 typedef long long int64; 16 typedef unsigned int uint; 17 typedef unsigned long long uint64; 18 19 #define gi(x) ((x) = F()) 20 #define gii(x, y) (gi(x), gi(y)) 21 #define giii(x, y, z) (gii(x, y), gi(z)) 22 23 int F() 24 { 25 char ch; 26 int x, a; 27 while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-'); 28 if (ch == '-') ch = getchar(), a = -1; 29 else a = 1; 30 x = ch - '0'; 31 while (ch = getchar(), ch >= '0' && ch <= '9') 32 x = (x << 1) + (x << 3) + ch - '0'; 33 return a * x; 34 } 35 36 const int N = 3010, mod = 1e9 + 7; 37 38 int inc(int a, int b) { a += b; return a >= mod ? a - mod : a; } 39 40 int n, m, f[N][N][2]; 41 42 int main() 43 { 44 gii(n, m); 45 for (int i = 0; i <= n; ++i) f[0][i][!!i] = 1; 46 for (int i = 1; i <= m; ++i) 47 { 48 for (int j = 0; j <= n; ++j) 49 { 50 //2 * x 51 f[i][j][0] = inc(f[i][j][0], f[i - 1][j + 1][0]); 52 f[i][j][!!j] = inc(f[i][j][!!j], f[i - 1][j + 1][1]); 53 54 //x ... y 55 if (j) f[i][j][0] = inc(f[i][j][0], f[i - 1][j][0]); 56 if (j) f[i][j][!!(j - 1)] = inc(f[i][j][!!(j - 1)], f[i - 1][j][1]); 57 58 //y ... x 59 if (j != n) f[i][j][0] = inc(f[i][j][0], f[i - 1][j][0]); 60 if (j != n) f[i][j][!!j] = inc(f[i][j][!!j], f[i - 1][j][1]); 61 62 //2 * y 63 if (j) f[i][j][0] = inc(f[i][j][0], f[i - 1][j - 1][0]); 64 if (j) f[i][j][1] = inc(f[i][j][1], f[i - 1][j - 1][1]); 65 } 66 } 67 int ans = 0; 68 for (int i = 0; i <= n; ++i) ans = inc(ans, f[m][i][0]); 69 printf("%d\n", ans); 70 return 0; 71 }
E - Placing Squares
写出n^2的dp式子:f[i]=sigma(f[j]*(i-j)^2),对于所有x[i],f[x[i]]=0。
我们考虑式子的组合意义,就是两个不同的球放在(i-j)箱子的方案数。
我们就可以dp[i][0/1/2]来线性递推了。
就可以用矩阵优化了。
1 //waz 2 #include <bits/stdc++.h> 3 4 using namespace std; 5 6 #define mp make_pair 7 #define pb push_back 8 #define fi first 9 #define se second 10 #define ALL(x) (x).begin(), (x).end() 11 #define SZ(x) ((int)((x).size())) 12 13 typedef pair<int, int> PII; 14 typedef vector<int> VI; 15 typedef long long int64; 16 typedef unsigned int uint; 17 typedef unsigned long long uint64; 18 19 #define gi(x) ((x) = F()) 20 #define gii(x, y) (gi(x), gi(y)) 21 #define giii(x, y, z) (gii(x, y), gi(z)) 22 23 int F() 24 { 25 char ch; 26 int x, a; 27 while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-'); 28 if (ch == '-') ch = getchar(), a = -1; 29 else a = 1; 30 x = ch - '0'; 31 while (ch = getchar(), ch >= '0' && ch <= '9') 32 x = (x << 1) + (x << 3) + ch - '0'; 33 return a * x; 34 } 35 36 const int mod = 1e9 + 7; 37 38 int inc(int a, int b) { a += b; return a >= mod ? a - mod : a; } 39 40 int n, m, x[100010]; 41 42 void task1() 43 { 44 static int dp[100010][3]; 45 dp[0][0] = 1; 46 static map<int, bool> X; 47 for (int i = 1; i <= m; ++i) X[x[i]] = 1; 48 for (int i = 1; i <= n; ++i) 49 { 50 dp[i][0] = dp[i - 1][0]; 51 dp[i][1] = inc(dp[i - 1][0], dp[i - 1][1]); 52 dp[i][2] = inc(inc(inc(dp[i - 1][0], dp[i - 1][1]), dp[i - 1][1]), dp[i - 1][2]); 53 if(!X.count(i - 1)) 54 { 55 dp[i][0] = inc(dp[i][0], dp[i - 1][2]); 56 dp[i][1] = inc(dp[i][1], dp[i - 1][2]); 57 dp[i][2] = inc(dp[i][2], dp[i - 1][2]); 58 } 59 } 60 printf("%d\n", dp[n][2]); 61 } 62 63 struct matrix 64 { 65 int a[3][3]; 66 friend matrix operator * (matrix a, matrix b) 67 { 68 matrix c; 69 memset(c.a, 0, sizeof c.a); 70 for (int k = 0; k < 3; ++k) 71 for (int i = 0; i < 3; ++i) 72 for (int j = 0; j < 3; ++j) 73 c.a[i][j] = (c.a[i][j] + 1LL * a.a[i][k] * b.a[k][j]) % mod; 74 return c; 75 } 76 } one, A, B, C; 77 78 matrix fpow(matrix a, int x) 79 { 80 matrix ret = one; 81 for (; x; x >>= 1) 82 { 83 if (x & 1) ret = ret * a; 84 a = a * a; 85 } 86 return ret; 87 } 88 89 void work() 90 { 91 /* 92 1,0,1 93 1,1,1 94 1,2,2 95 */ 96 /* 97 1,0,0 98 1,1,0 99 1,2,1 100 */ 101 one.a[0][0] = one.a[1][1] = one.a[2][2] = 1; 102 A.a[0][0] = 1, A.a[0][1] = 0, A.a[0][2] = 1; 103 A.a[1][0] = 1, A.a[1][1] = 1, A.a[1][2] = 1; 104 A.a[2][0] = 1, A.a[2][1] = 2, A.a[2][2] = 2; 105 B.a[0][0] = 1, B.a[0][1] = 0, B.a[0][2] = 0; 106 B.a[1][0] = 1, B.a[1][1] = 1, B.a[1][2] = 0; 107 B.a[2][0] = 1, B.a[2][1] = 2, B.a[2][2] = 1; 108 matrix ret = one; 109 for (int i = 1; i <= m; ++i) 110 { 111 ret = ret * fpow(A, x[i] - x[i - 1] - 1); 112 ret = ret * B; 113 } 114 ret = ret * fpow(A, n - x[m]); 115 C.a[0][0] = 1; 116 ret = ret * C; 117 printf("%d\n", ret.a[2][0]); 118 } 119 120 int main() 121 { 122 gii(n, m); 123 for (int i = 1; i <= m; ++i) gi(x[i]); 124 //task1(); 125 work(); 126 return 0; 127 }
F - Two Faced Cards
不会做,先咕着(目前已经咕了4题了qwq)。