第三周 7.24-7.30
7.24
HDU 1402 A * B Problem Plus
抄板。
1 // HDU 1402 A * B Problem Plus 2 #include <iostream> 3 #include <cstdio> 4 #include <cmath> 5 #include <cstring> 6 #include <algorithm> 7 using namespace std; 8 const int maxn = 5e4 + 10; 9 int a[maxn], b[maxn], c[maxn<<2]; 10 char s1[maxn], s2[maxn]; 11 12 // FFT 13 const double Pi = acos(-1.0); 14 15 struct complex 16 { 17 double r, i; 18 complex(double r = 0, double i = 0): r(r), i(i) {} 19 complex operator + (const complex &ot) const 20 { 21 return complex(r + ot.r, i + ot.i); 22 } 23 complex operator - (const complex &ot) const 24 { 25 return complex(r - ot.r, i - ot.i); 26 } 27 complex operator * (const complex &ot) const 28 { 29 return complex(r * ot.r - i * ot.i, r * ot.i + i * ot.r); 30 } 31 } x1[maxn<<2], x2[maxn<<2]; 32 33 void change(complex * y, int len) 34 { 35 for(int i = 1, j = len >> 1; i < len - 1; i++) 36 { 37 if(i < j) swap(y[i], y[j]); 38 int k = len >> 1; 39 while(j >= k) j -= k, k >>= 1; 40 j += k; 41 } 42 } 43 44 void FFT(complex * y, int len, int on) 45 { 46 change(y, len); 47 for(int h = 2; h <= len; h <<= 1) 48 { 49 complex wn = complex(cos(on * 2 * Pi / h), sin(on * 2 * Pi / h)); 50 for(int j = 0; j < len; j += h) 51 { 52 complex w = complex(1, 0); 53 for(int k = j; k < j + h / 2; k++) 54 { 55 complex u = y[k]; 56 complex t = y[k+h/2] * w; 57 y[k] = u + t; 58 y[k+h/2] = u - t; 59 w = w * wn; 60 } 61 } 62 } 63 if(on == -1) 64 { 65 for(int i = 0; i < len; i++) 66 { 67 y[i].r /= len; 68 } 69 } 70 } 71 72 void cal(int * a, int * b, int * c, int l) 73 { 74 int len = 1; 75 while(len < l * 2) len <<= 1; 76 for(int i = 0; i < l; i++) 77 { 78 x1[i] = complex(a[i], 0); 79 x2[i] = complex(b[i], 0); 80 } 81 for(int i = l; i < len; i++) x1[i] = x2[i] = complex(0, 0); 82 FFT(x1, len, 1); 83 FFT(x2, len, 1); 84 for(int i = 0; i < len; i++) x1[i] = x1[i] * x2[i]; 85 FFT(x1, len, -1); 86 for(int i = 0; i < len; i++) 87 c[i] = x1[i].r + 0.5; 88 } 89 90 int main(void) 91 { 92 while(~scanf("%s %s", s1, s2)) 93 { 94 int l1 = strlen(s1), l2 = strlen(s2); 95 int l = max(l1, l2); 96 for(int i = 0; i < l; i++) 97 { 98 a[i] = l1 - i - 1 >= 0 ? s1[l1-i-1] - '0' : 0; 99 b[i] = l2 - i - 1 >= 0 ? s2[l2-i-1] - '0' : 0; 100 } 101 102 memset(c, 0, sizeof(c)); 103 cal(a, b, c, l); 104 for(int i = 0; i < l1 + l2; i++) 105 { 106 c[i+1] += c[i] / 10; 107 c[i] %= 10; 108 } 109 110 int st = 0; 111 for(int i = l1 + l2; i >= 0; i--) 112 { 113 if(!st && !c[i] && i) continue; 114 st = 1; 115 printf("%d", c[i]); 116 } 117 puts(""); 118 } 119 return 0; 120 }
补套BC。
HDU 5747 Aaronson
很好写的水题哟。
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 int main(void) 6 { 7 int T; 8 scanf("%d", &T); 9 while(T--) 10 { 11 int n, m; 12 scanf("%d %d", &n, &m); 13 int ans = 0; 14 while(n && m) 15 { 16 if(n % 2) ans++; 17 n /= 2, m--; 18 } 19 ans += n; 20 printf("%d\n", ans); 21 } 22 return 0; 23 }
HDU 5448 Bellovin
看sample可能会猜出就是答案dp数组。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 const int maxn = 1e5 + 10; 7 int f[maxn]; 8 9 struct node 10 { 11 int p, a; 12 friend bool operator < (node A, node B) 13 { 14 if(A.a != B.a) return A.a < B.a; 15 return A.p > B.p; 16 } 17 } num[maxn]; 18 19 // BIT 20 int c[maxn]; 21 int lowbit(int s) 22 { 23 return s & (-s); 24 } 25 void modify(int i, int x) 26 { 27 while(i < maxn) c[i] = max(c[i], x), i += lowbit(i); 28 return; 29 } 30 int query(int i) 31 { 32 int ret = 0; 33 while(i > 0) ret = max(ret, c[i]), i -= lowbit(i); 34 return ret; 35 } 36 37 int main(void) 38 { 39 int T; 40 scanf("%d", &T); 41 while(T--) 42 { 43 int N; 44 scanf("%d", &N); 45 for(int i = 1; i <= N; i++) 46 { 47 scanf("%d", &num[i].a); 48 num[i].p = i; 49 } 50 sort(num + 1, num + 1 + N); 51 52 memset(c, 0, sizeof(c)); 53 for(int i = 1; i <= N; i++) 54 { 55 int p = num[i].p; 56 f[p] = query(p) + 1; 57 modify(p, f[p]); 58 } 59 60 for(int i = 1; i < N; i++) printf("%d ", f[i]); 61 printf("%d\n", f[N]); 62 } 63 return 0; 64 }
HDU 5449 Colmerauer
因为每个鞍点的贡献是它的值乘上所在矩阵的覆盖面积,
先用n2预处理了f[l][r]表示一条线段左边延伸l,右边延伸r的所有子线段和。
再用单调栈四个方向处理每个数在l,r,u,d范围内是鞍点。
这样一来f[l][r]乘f[u][d]就是所有子矩阵的面积和拉。
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 typedef unsigned int ui; 5 int l[1111][1111], r[1111][1111]; 6 int u[1111][1111], d[1111][1111]; 7 ui M[1111][1111], f[1111][1111]; 8 9 int main(void) 10 { 11 for(ui i = 0; i <= 1000; i++) 12 { 13 f[i][0] = i ? f[i-1][0] + i + 1 : 1; 14 for(ui j = 1; j <= 1000; j++) 15 f[i][j] = f[i][j-1] + (i + 1) * (j + 1) + i * (i + 1) / 2; 16 } 17 18 int T; 19 scanf("%d", &T); 20 while(T--) 21 { 22 int n, m; 23 scanf("%d %d", &n, &m); 24 for(int i = 1; i <= n; i++) 25 for(int j = 1; j <= m; j++) 26 scanf("%u", &M[i][j]); 27 28 // l 29 for(int i = 1; i <= n; i++) 30 { 31 int st[1111], p = 0; 32 for(int j = 1; j <= m; j++) 33 { 34 while(p && M[i][st[p]] > M[i][j]) p--; 35 l[i][j] = p ? (j - st[p] - 1) : (j - 1); 36 st[++p] = j; 37 } 38 } 39 40 // r 41 for(int i = 1; i <= n; i++) 42 { 43 int st[1111], p = 0; 44 for(int j = m; j >= 1; j--) 45 { 46 while(p && M[i][st[p]] > M[i][j]) p--; 47 r[i][j] = p ? (st[p] - j - 1) : (m - j); 48 st[++p] = j; 49 } 50 } 51 52 // u 53 for(int j = 1; j <= m; j++) 54 { 55 int st[1111], p = 0; 56 for(int i = 1; i <= n; i++) 57 { 58 while(p && M[st[p]][j] < M[i][j]) p--; 59 u[i][j] = p ? (i - st[p] - 1) : (i - 1); 60 st[++p] = i; 61 } 62 } 63 64 // d 65 for(int j = 1; j <= m; j++) 66 { 67 int st[1111], p = 0; 68 for(int i = n; i >= 1; i--) 69 { 70 while(p && M[st[p]][j] < M[i][j]) p--; 71 d[i][j] = p ? (st[p] - i - 1) : (n - i); 72 st[++p] = i; 73 } 74 } 75 76 77 ui ans = 0; 78 for(int i = 1; i <= n; i++) 79 { 80 for(int j = 1; j <= m; j++) 81 { 82 int L = l[i][j], R = r[i][j]; 83 int U = u[i][j], D = d[i][j]; 84 ans = ans + M[i][j] * f[L][R] * f[U][D]; 85 } 86 } 87 printf("%u\n", ans); 88 89 } 90 return 0; 91 }
HDU 5450 Dertouzos
在打筛表的时候就可以算出md了。然后就是题解那样搞。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 const int maxn = 1e7 + 10; 6 int pr[maxn], md[maxn]; 7 8 void GetPrime() 9 { 10 for(int i = 2; i < maxn; i++) 11 { 12 if(!pr[i]) pr[++pr[0]] = i, md[i] = i; 13 for(int j = 1; j <= pr[0] && pr[j] * i < maxn; j++) 14 { 15 pr[i*pr[j]] = 1; 16 md[i*pr[j]] = pr[j]; 17 if(i % pr[j] == 0) break; 18 } 19 } 20 } 21 22 int main(void) 23 { 24 GetPrime(); 25 int T; 26 scanf("%d", &T); 27 while(T--) 28 { 29 int n, d; 30 scanf("%d %d", &n, &d); 31 int ans = 0; 32 if(d < maxn) ans = upper_bound(pr + 1, pr + pr[0], min((n - 1) / d, md[d])) - pr - 1; 33 else for(int i = 1; i <= pr[0] && pr[i] <= (n - 1) / d; i++) 34 { 35 ans++; 36 if(d % pr[i] == 0) break; 37 } 38 printf("%d\n", ans); 39 } 40 return 0; 41 }
HDU 5451 Eades
对于每个数找区间那里不会搞,找了个AC代码抄了一下。
大概是用一个随便什么存一下区间最大值,先solve(l, r)算这个区间的最大值的贡献,
然后找到所有最大值的位置,所有的最大值把l,r切成了好多小区间,每个小区间递归一下。
这样搞也许可能大概是差不多nlogn的吧。
然后就是纯粹的FFT,虽然不懂怎么搞但是抄个板还是可以的。
然而算了半天发现推的式子和AC代码不一样QAQ。
结果竟然也对了真是神奇哦。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <cmath> 6 #include <algorithm> 7 using namespace std; 8 const int maxn = 1e5 + 10; 9 typedef long long LL; 10 vector<int> p[maxn]; 11 int n, a[maxn], b[maxn], z[maxn]; 12 13 // ST 14 int rmq[maxn][20]; 15 void RMQ_init() 16 { 17 for(int i = 1; i <= n; i++) rmq[i][0] = a[i]; 18 for(int j = 1; (1 << j) <= n; j++) 19 for(int i = 1; i + ( 1 << j ) - 1 <= n; i++) 20 rmq[i][j] = max(rmq[i][j-1] , rmq[i+(1<<j-1)][j-1]); 21 } 22 23 int RMQ_query(int l, int r) 24 { 25 int k = 0; 26 while( ( 1 << (k + 1) ) <= r - l + 1 ) k++; 27 return max(rmq[l][k], rmq[r-(1<<k)+1][k]); 28 } 29 30 31 // FFT 32 const double Pi = acos(-1.0); 33 34 struct complex 35 { 36 double r, i; 37 complex(double r = 0, double i = 0): r(r), i(i) {} 38 complex operator + (const complex &ot) const 39 { 40 return complex(r + ot.r, i + ot.i); 41 } 42 complex operator - (const complex &ot) const 43 { 44 return complex(r - ot.r, i - ot.i); 45 } 46 complex operator * (const complex &ot) const 47 { 48 return complex(r * ot.r - i * ot.i, r * ot.i + i * ot.r); 49 } 50 } x1[maxn<<2], x2[maxn<<2]; 51 52 void change(complex * y, int len) 53 { 54 for(int i = 1, j = len >> 1; i < len - 1; i++) 55 { 56 if(i < j) swap(y[i], y[j]); 57 int k = len >> 1; 58 while(j >= k) j -= k, k >>= 1; 59 j += k; 60 } 61 } 62 63 void FFT(complex * y, int len, int on) 64 { 65 change(y, len); 66 for(int h = 2; h <= len; h <<= 1) 67 { 68 complex wn = complex(cos(on * 2 * Pi / h), sin(on * 2 * Pi / h)); 69 for(int j = 0; j < len; j += h) 70 { 71 complex w = complex(1, 0); 72 for(int k = j; k < j + h / 2; k++) 73 { 74 complex u = y[k]; 75 complex t = y[k+h/2] * w; 76 y[k] = u + t; 77 y[k+h/2] = u - t; 78 w = w * wn; 79 } 80 } 81 } 82 if(on == -1) 83 { 84 for(int i = 0; i < len; i++) 85 { 86 y[i].r /= len; 87 } 88 } 89 } 90 91 void cal(int * a, int * b, int l) 92 { 93 int len = 1; 94 while(len < l * 2) len <<= 1; 95 for(int i = 0; i < l; i++) 96 { 97 x1[i] = complex(a[i], 0); 98 x2[i] = complex(b[i], 0); 99 } 100 for(int i = l; i < len; i++) x1[i] = x2[i] = complex(0, 0); 101 FFT(x1, len, 1); 102 FFT(x2, len, 1); 103 for(int i = 0; i < len; i++) x1[i] = x1[i] * x2[i]; 104 FFT(x1, len, -1); 105 for(int i = 1; i < l; i++) 106 z[i] += x1[l-1-i].r + 0.5; 107 } 108 109 void solve(int l, int r) 110 { 111 if(l > r) return; 112 if(l == r) {z[1]++; return;} 113 int M = RMQ_query(l, r); 114 int x = lower_bound(p[M].begin(), p[M].end(), l) - p[M].begin(); 115 int y = upper_bound(p[M].begin(), p[M].end(), r) - p[M].begin() - 1; 116 117 a[0] = p[M][x] - l + 1; 118 for(int i = x + 1; i <= y; i++) a[i-x] = p[M][i] - p[M][i-1]; 119 a[y-x+1] = r - p[M][y] + 1; 120 121 for(int i = 0; i <= y - x + 1; i++) b[i] = a[y-x+1-i]; 122 123 cal(a, b, y - x + 2); 124 125 solve(l, p[M][x] - 1); 126 for(int i = x + 1; i <= y; i++) solve(p[M][i-1] + 1, p[M][i] - 1); 127 solve(p[M][y] + 1, r); 128 } 129 130 int main(void) 131 { 132 int T; 133 scanf("%d", &T); 134 while(T--) 135 { 136 scanf("%d", &n); 137 for(int i = 1; i <= n; i++) p[i].clear(); 138 for(int i = 1; i <= n; i++) 139 { 140 scanf("%d", a + i); 141 p[a[i]].push_back(i); 142 } 143 RMQ_init(); 144 memset(z, 0, sizeof(z)); 145 solve(1, n); 146 LL ans = 0; 147 for(int i = 1; i <= n; i++) ans += (LL) i ^ z[i]; 148 printf("%I64d\n", ans); 149 } 150 return 0; 151 }
补题
HDU 5584 LCM Walk
gcd不会变呀。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 6 int gcd(int a, int b) 7 { 8 return a % b ? gcd(b, a % b) : b; 9 } 10 11 int main(void) 12 { 13 int T; 14 scanf("%d", &T); 15 for(int kase = 1; kase <= T; kase++) 16 { 17 int a, b; 18 scanf("%d %d", &a, &b); 19 int ans = 1; 20 while(1) 21 { 22 if(a < b) swap(a, b); 23 int tmp = 1 + b / gcd(a, b); 24 if(a % tmp) break; 25 a /= tmp; 26 if(gcd(a, b) != b / (tmp - 1)) break; 27 ans++; 28 } 29 printf("Case #%d: %d\n", kase, ans); 30 } 31 return 0; 32 }
7.25
HDU 5487 Difference of Languages
BFS。如果想到状态用<state 1, state 2>表示就好写了。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 using namespace std; 6 typedef pair<int, int> pii; 7 8 int is[2][1111], nxt[2][1111][26]; 9 10 pii pre[1111][1111]; 11 int vis[1111][1111]; 12 int a[1111][1111]; 13 14 queue<pii> Q; 15 16 void ans_print(pii cur) 17 { 18 int c1 = cur.first, c2 = cur.second; 19 if(c1 || c2) 20 { 21 ans_print(pre[c1][c2]); 22 printf("%c", a[c1][c2] + 'a'); 23 } 24 } 25 26 int main(void) 27 { 28 int T; 29 scanf("%d", &T); 30 for(int kase = 1; kase <= T; kase++) 31 { 32 memset(is, 0, sizeof(is)); 33 memset(vis, 0, sizeof(vis)); 34 memset(nxt, -1, sizeof(nxt)); 35 36 int N1, M1, K1; 37 scanf("%d %d %d", &N1, &M1, &K1); 38 for(int i = 0; i < K1; i++) 39 { 40 int x; 41 scanf("%d", &x); 42 is[0][x] = 1; 43 } 44 for(int i = 0; i < M1; i++) 45 { 46 int p, q; 47 char s[10]; 48 scanf("%d %d %s", &p, &q, s); 49 nxt[0][p][s[0]-'a'] = q; 50 } 51 52 int N2, M2, K2; 53 scanf("%d %d %d", &N2, &M2, &K2); 54 for(int i = 0; i < K2; i++) 55 { 56 int x; 57 scanf("%d", &x); 58 is[1][x] = 1; 59 } 60 for(int i = 0; i < M2; i++) 61 { 62 int p, q; 63 char s[10]; 64 scanf("%d %d %s", &p, &q, s); 65 nxt[1][p][s[0]-'a'] = q; 66 } 67 68 while(!Q.empty()) Q.pop(); 69 70 int ok = 0; 71 pii ans; 72 Q.push(pii(0, 0)); 73 while(!Q.empty()) 74 { 75 pii tmp = Q.front(); Q.pop(); 76 int c1 = tmp.first, c2 = tmp.second; 77 if(is[0][c1] && !is[1][c2] || !is[0][c1] && is[1][c2]){ans = tmp, ok = 1; break;} 78 79 for(int i = 0; i < 26; i++) 80 { 81 int nx1 = N1, nx2 = N2; 82 if(c1 < N1 && nxt[0][c1][i] != -1) nx1 = nxt[0][c1][i]; 83 if(c2 < N2 && nxt[1][c2][i] != -1) nx2 = nxt[1][c2][i]; 84 if(vis[nx1][nx2]) continue; 85 vis[nx1][nx2] = 1; 86 pre[nx1][nx2] = pii(c1, c2); 87 a[nx1][nx2] = i; 88 Q.push(pii(nx1, nx2)); 89 } 90 } 91 92 printf("Case #%d: ", kase); 93 if(ok) ans_print(ans), puts(""); 94 else puts("0"); 95 96 } 97 return 0; 98 }