ABC 选做(2000<=Difficulty<3200)
ABC003D(Difficulty:2033)
部分分 $D+L=X\times Y$ 答案显然为 $(R-X+1)\times (C-Y+1)\times\dbinom{X\times Y}{D}$。
考虑分成没有卡到上方、下方、左侧、右侧的四个集合,容斥出答案即可,代码用四位二进制数实现比较简单。
1 const int N = 910; 2 const ll p = 1e9 + 7; 3 int r, c, x, y, d, l; 4 ll ans, binom[N][N]; 5 6 inline void addmod(ll &x, ll y) { x += y; if (x >= p) x -= p; } 7 inline void submod(ll &x, ll y) { x -= y; if (x < 0) x += p; } 8 9 int main() 10 { 11 read(r, c, x, y, d, l); 12 for (int i = 0; i <= x * y; ++i) 13 { 14 binom[i][0] = 1; 15 for (int j = 1; j <= i; ++j) 16 addmod(binom[i][j], binom[i - 1][j] + binom[i - 1][j - 1]); 17 } 18 for (int i = 0; i < 16; ++i) 19 { 20 int xx = x, yy = y; 21 if (i >> 0 & 1) --xx; 22 if (i >> 1 & 1) --xx; 23 if (i >> 2 & 1) --yy; 24 if (i >> 3 & 1) --yy; 25 if (xx <= 0 || yy <= 0) continue; 26 if (__builtin_popcount(i) & 1) 27 submod(ans, binom[xx * yy][d + l] * binom[d + l][d] % p); 28 else addmod(ans, binom[xx * yy][d + l] * binom[d + l][d] % p); 29 } 30 ans = ans * (r - x + 1) % p * (c - y + 1) % p; print(ans, '\n'); 31 flush_pbuf(); return 0; 32 }
ABC008D(Difficulty:2203)
$2^{30}\approx10^9$,时限还开到 4s,直接暴力记搜就完了,注意 $O(\log)$ 存状态被卡了,需要手写 hash 表 $O(1)$ 存状态。
理论上状态量很大,实际上根本跑不满,这份代码最慢的点 40-ms 就冲过去了,所以这题是不是可以加强到 $n\le35$ 时限 2s 啊/se
1 const int N = 35; 2 int w, h, n, x[N], y[N]; 3 struct node 4 { 5 int _x1, _y1, _x2, _y2; 6 node() {} 7 node(int a, int b, int c, int d) : _x1(a), _y1(b), _x2(c), _y2(d) {} 8 inline bool operator == (const node &x) const 9 { 10 return _x1 == x._x1 && _y1 == x._y1 && _x2 == x._x2 && _y2 == x._y2; 11 } 12 }; 13 14 struct hash_table 15 { 16 static const int P = 1e7 + 19; 17 const ll b1 = 131, b2 = b1 * b1, b3 = b2 * b1; 18 int tot, h[P]; 19 struct data 20 { 21 node x; ll val; int nxt; 22 data() {} 23 data(node _x, ll _val, int _nxt) : x(_x), val(_val), nxt(_nxt) {} 24 } e[P << 1]; 25 26 inline void clear() { tot = 0, memset(h, 0, sizeof(h)); } 27 inline int hash(node x) { return (x._x1 * b3 + x._y1 * b2 + x._x2 * b1 + x._y2) % P; } 28 29 inline ll& operator [] (node x) 30 { 31 int pos = hash(x); 32 for (int i = h[pos]; i; i = e[i].nxt) 33 if (e[i].x == x) return e[i].val; 34 e[++tot] = data(x, -1, h[pos]), h[pos] = tot; 35 return e[tot].val; 36 } 37 } Map; 38 39 ll dfs(int _x1, int _y1, int _x2, int _y2) 40 { 41 if (_x1 > _x2 || _y1 > _y2) return 0; 42 node a = node(_x1, _y1, _x2, _y2); 43 if (~Map[a]) return Map[a]; 44 for (int i = 1; i <= n; ++i) 45 if (_x1 <= x[i] && x[i] <= _x2 && _y1 <= y[i] && y[i] <= _y2) 46 { 47 Map[a] = Max(Map[a], dfs(_x1, _y1, x[i] - 1, y[i] - 1) + 48 dfs(_x1, y[i] + 1, x[i] - 1, _y2) + dfs(x[i] + 1, _y1, _x2, y[i] - 1) + 49 dfs(x[i] + 1, y[i] + 1, _x2, _y2) + _x2 - _x1 + _y2 - _y1 + 1); 50 } 51 return Max(Map[a], 0ll); 52 } 53 54 int main() 55 { 56 read(w, h, n); 57 for (int i = 1; i <= n; ++i) read(x[i], y[i]); 58 print(dfs(1, 1, w, h), '\n'); 59 flush_pbuf(); return 0; 60 }
ABC009D(Difficulty:2213)
将 AND 视作乘法,将 XOR 视作加法,$k\le100,\ m\le10^9$,显然是矩阵快速幂。
单位矩阵为:
$$ \begin{bmatrix} 2^{32}-1 & 0 & \cdots & 0 & 0 \\ 0 & 2^{32}-1 & \cdots & 0 & 0 \\ \vdots & \vdots & \ddots & \vdots & \vdots \\ 0 & 0 & \cdots & 2^{32}-1 & 0 \\ 0 & 0 & \cdots & 0 & 2^{32}-1 \end{bmatrix} $$
公式为:
$$ \begin{bmatrix} c_1 & c_2 & \cdots & c_{k-2} & c_{k-1} & c_k \\ 2^{32}-1 & 0 & \cdots & 0 & 0 & 0 \\ 0 & 2^{32}-1 & \cdots & 0 & 0 & 0 \\ \vdots & \vdots & \ddots & \vdots & \vdots & \vdots \\ 0 & 0 & \cdots & 2^{32}-1 & 0 & 0 \\ 0 & 0 & \cdots & 0 & 2^{32}-1 & 0 \end{bmatrix}^{m-k} \cdot \begin{bmatrix} a_k \\ a_{k-1} \\ a_{k-2} \\ \vdots \\ a_2 \\ a_1 \end{bmatrix} = \begin{bmatrix} a_{m} \\ a_{m-1} \\ a_{m-2} \\ \vdots \\ a_{m-k+2} \\ a_{m-k+1} \end{bmatrix}$$
注意特判 $m\le k$ 的情况。
1 const int N = 105; 2 const unsigned int I = -1; 3 int n, m; 4 unsigned int a[N], c[N]; 5 struct matrix 6 { 7 unsigned int a[N][N]; 8 matrix() { clear(); } 9 inline void clear() { memset(a, 0, sizeof(a)); } 10 inline void init() 11 { 12 for (int i = 1; i <= n; ++i) 13 for (int j = 1; j <= n; ++j) 14 i == j ? a[i][j] = I : a[i][j] = 0; 15 } 16 } f, g; 17 inline matrix operator * (const matrix &x, const matrix &y) 18 { 19 matrix res; 20 for (int i = 1; i <= n; ++i) 21 for (int k = 1; k <= n; ++k) 22 for (int j = 1; j <= n; ++j) 23 res.a[i][j] ^= x.a[i][k] & y.a[k][j]; 24 return res; 25 } 26 inline matrix power(matrix x, int y) 27 { 28 matrix res; res.init(); 29 for (; y; y >>= 1, x = x * x) 30 if (y & 1) res = res * x; 31 return res; 32 } 33 34 int main() 35 { 36 read(n, m); 37 for (int i = 1; i <= n; ++i) read(a[i]); 38 for (int i = 1; i <= n; ++i) read(c[i]); 39 if (m <= n) { print(a[m], '\n'); flush_pbuf(); return 0; } 40 for (int i = 1; i <= n; ++i) 41 { 42 f.a[1][i] = c[i]; 43 if (i < n) f.a[i + 1][i] = I; 44 g.a[n - i + 1][1] = a[i]; 45 } 46 f = power(f, m - n), g = f * g; 47 print(g.a[1][1], '\n'); 48 flush_pbuf(); return 0; 49 }
ABC020D(Difficulty:2695)
推一下柿子:
$$ \begin{split} & \sum\limits_{i=1}^n \operatorname{lcm}(i,k) \\ = & \sum\limits_{i=1}^n \dfrac{i\cdot k}{\gcd(i,k)} \\ = & k \sum\limits_{i=1}^n \dfrac{i}{d} \cdot [\gcd(i,k)=d] \\ = & k \sum\limits_{d\mid k} \sum\limits_{i=1}^{\frac{n}{d}} i \cdot [\gcd(i,\frac{k}{d})=1] \end{split} $$
因此问题转化为给定 $m,d$ 求 $\sum\limits_{i=1}^m i\cdot [\gcd(i,d)=1]$,容斥即可。
总时间复杂度上界为 $O(\sqrt{k}+d(k)\cdot 2^{\omega(k)}\cdot \omega(k))$,实际上根本跑不满。
1 const ll p = 1e9 + 7; 2 vector<int> d, omega; 3 4 inline void get_d(int k) 5 { 6 for (int i = 1; i * i <= k; ++i) 7 if (!(k % i)) 8 { 9 d.emplace_back(i); 10 if (i != k / i) d.emplace_back(k / i); 11 } 12 } 13 inline void get_omega(int k) 14 { 15 for (int i = 2; i * i <= k; ++i) 16 if (!(k % i)) 17 { 18 omega.emplace_back(i); 19 while (!(k % i)) k /= i; 20 } 21 if (k > 1) omega.emplace_back(k); 22 } 23 24 inline void addmod(ll &x, ll y) { x += y; if (x >= p) x -= p; } 25 inline void submod(ll &x, ll y) { x -= y; if (x < 0) x += p; } 26 27 inline ll solve(int n, int k) 28 { 29 vector<int>().swap(omega); get_omega(k); ll res = 0; 30 for (int i = 0; i < 1 << omega.size(); ++i) 31 { 32 int GCD = 1; 33 for (int j = 0; j < omega.size(); ++j) 34 if (i >> j & 1) GCD *= omega[j]; 35 ll cnt = (n / GCD + 1ll) * (n / GCD) / 2; cnt %= p; 36 if (__builtin_popcount(i) & 1) submod(res, cnt * GCD % p); 37 else addmod(res, cnt * GCD % p); 38 } 39 return res; 40 } 41 42 int main() 43 { 44 int n, k; ll ans = 0; read(n, k); get_d(k); 45 for (int i = 0; i < d.size(); ++i) 46 addmod(ans, solve(n / d[i], k / d[i]) * k % p); 47 print(ans, '\n'); 48 flush_pbuf(); return 0; 49 }
ABC024D(Difficulty:2050)
设 $a=\dfrac{A}{B}=\dfrac{\binom{n+m}{n}}{\binom{n+m+1}{n}}=\dfrac{m+1}{n+m+1},\ b=\dfrac{A}{C}=\dfrac{\binom{n+m}{n}}{\binom{n+m+1}{m}}=\dfrac{n+1}{n+m+1}$。
由此解出 $n=\dfrac{a-1}{-a-b+1},\ m=\dfrac{b-1}{-a-b+1}$。
1 const ll p = 1e9 + 7; 2 3 inline ll power(ll x, ll y) 4 { 5 ll res = 1; 6 for (; y; y >>= 1, x = x * x % p) 7 if (y & 1) res = res * x % p; 8 return res; 9 } 10 11 int main() 12 { 13 ll A, B, C, a, b, n, m; read(A, B, C); 14 a = A * power(B, p - 2) % p, b = A * power(C, p - 2) % p; 15 n = (a - 1) * power(-a - b + 1, p - 2) % p; if (n < 0) n += p; 16 m = (b - 1) * power(-a - b + 1, p - 2) % p; if (m < 0) m += p; 17 print(n, ' ', m, '\n'); 18 flush_pbuf(); return 0; 19 }
ABC025D(Difficulty:3006)
ABC027D(Difficulty:2088)
ABC033D(Difficulty:2248)
To be continued...