湖南省队集训 Day 2

  暴力分又没骗满sad.....

Problem A 走路

 

  $O(n^2)$动态规划是显然的。

  更新方式有两种:一种是枚举它的倍数转移,一种是转移到它的约数。

  考虑利用分块来平衡一下(像分块FWT一样)。

  注意到若$x = ab, y = cd, (a, b) = 1, (c, d) = 1$,那么$x | y$的充分必要条件是$a | c, b | d$或者$a | d, b | c$。

  那么我们可以把$v_1$拆成$AB, (A, B) = 1$,使得$A$和$B$的约数个数尽量相等。

  对于每一部分,离散化后暴力处理整除关系。每次修改或查询时固定一维动另一维。

  时间复杂度$O(nV^{0.25})$。

Code

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <cassert>
  4 #include <cstdlib>
  5 #include <cstdio>
  6 #include <vector>
  7 #include <ctime>
  8 #ifndef WIN32
  9 #define Auto "%lld"
 10 #else
 11 #define Auto "%I64d"
 12 #endif
 13 using namespace std;
 14 typedef bool boolean;
 15 
 16 #define ll long long
 17 #define ull unsigned long long
 18 
 19 template <typename T>
 20 T add(T a, T b, T m) {
 21     return ((a += b) >= m) ? (a - m) : (a);
 22 }
 23 
 24 template <typename T>
 25 T sub(T a, T b, T m) {
 26     return ((a -= b) < 0) ? (a + m) : (a);
 27 }
 28 
 29 template <typename T>
 30 void pcopy(T* pst, const T* ped, T* pval) {
 31     for ( ; pst != ped; *(pst++) = *(pval++));
 32 }
 33 
 34 template <typename T>
 35 void pfill(T* pst, const T* ped, T val) {
 36     for ( ; pst != ped; *(pst++) = val);
 37 }
 38 
 39 ll mul(ll a, ll b, ll m) {
 40 //    return (__int128)a * b % m;
 41     ll rt = 0, pa = a;
 42     for ( ; b; b >>= 1, pa = add(pa, pa, m))
 43         if (b & 1)
 44             rt = add(rt, pa, m);
 45     return rt;
 46 }
 47 
 48 ll qpow(ll a, ll p, ll m) {
 49     ll rt = 1, pa = a;
 50     for ( ; p; p >>= 1, pa = mul(pa, pa, m))
 51         if (p & 1)
 52             rt = mul(rt, pa, m);
 53     return rt;
 54 }
 55 
 56 ll gcd(ll a, ll b) {
 57     return (b) ? (gcd(b, a % b)) : (a);
 58 }
 59 
 60 ll randLL() {
 61     static ull seed = 998244353, msk = (1ull << 61) - 1;
 62     return (signed ll) ((seed = seed * seed + seed + 233) & msk);
 63 }
 64 
 65 int pri[8] = {2, 3, 5, 7, 11, 13, 17, 19};
 66 
 67 boolean miller_rabin(ll n) {
 68     static int T = 25;
 69     for (int i = 0; i < 8; i++)
 70         if (!(n % pri[i]))
 71             return n == pri[i];
 72     if (n < 1000) {
 73         for (int p = 2; p * p <= n; p++)
 74             if (!(n % p))
 75                 return false;
 76         return true;
 77     }
 78     ll d = n - 1;
 79     int s = 0;
 80     while (!(d & 1))
 81         s++, d >>= 1;
 82     for (int t = 0; t < T; t++) {
 83         ll b = randLL() % n;
 84         if (!b)
 85             continue;
 86         ll tmp = qpow(b, d, n);
 87         if (tmp == 1 || tmp == n - 1)
 88             continue;
 89         for (int i = 0; i < s; i++) {
 90             tmp = mul(tmp, tmp, n);
 91             if (tmp == n - 1)
 92                 goto nextTurn;
 93             if (tmp == 1 || tmp == 0)
 94                 return false;
 95         }
 96         if (tmp != 1)
 97             return false;
 98         nextTurn:;
 99     }
100     return true;
101 }
102 
103 ll pollard_rho(ll x) {
104     ll a, b, c, g;
105     if (!(x & 1))
106         return 2;
107     while (true) {
108         b = a = randLL() % x;
109         c = randLL() % 127;
110         do {
111             a = add(mul(a, a, x), c, x);
112             b = add(mul(b, b, x), c, x);
113             b = add(mul(b, b, x), c, x);
114             g = gcd(b - a, x);
115             (g < 0) ? (g = -g) : (0);
116             if (g == x)
117                 break;
118             if (g > 1)
119                 return g;
120         } while (a != b);
121     }
122     assert(false);
123     return 0;
124 }
125 
126 void get_primary_factors(ll x, vector<ll>& rt) {
127     if (miller_rabin(x)) {
128         rt.push_back(x);
129         return;
130     }
131     ll a = pollard_rho(x);
132     get_primary_factors(a, rt);
133     get_primary_factors(x / a, rt);
134 }
135 
136 vector< pair<ll, int> > get_primary_factor(vector<ll>& vec) {
137     vector< pair<ll, int> > rt;
138     if (vec.empty())
139         return rt;
140     sort(vec.begin(), vec.end());
141     vector<ll>::iterator it = vec.begin();
142     rt.push_back(make_pair(*it, 1));
143     for (it = it + 1 ; it != vec.end(); it++)
144         if (*it == rt.back().first)
145             rt.back().second++;
146         else
147             rt.push_back(make_pair(*it, 1));
148     return rt;
149 }
150 
151 typedef vector< pair<ll, int> > factor;
152 
153 /// Template ends
154 
155 template <typename T>
156 class Matrix {
157     public:
158         T* p;
159         int r, c;
160 
161         Matrix() : p(NULL) {    }
162         Matrix(int r, int c) : r(r), c(c) {
163             p = new T[r * c];
164         }
165 
166         T* operator [] (int pos) {
167             return p + c * pos;
168         }
169 };
170 
171 const int Mod = 1e9 + 7;
172 
173 int n;
174 ll *v;
175 int *f;
176 Matrix<int> F;
177 vector<int> *g;
178 vector<ll> va, vb;
179 vector<int> *diva, *divb, *mula, *mulb;
180 
181 inline void init() {
182     scanf("%d", &n);
183     g = new vector<int>[(n + 1)];
184     for (int i = 1, u, v; i < n; i++) {
185         scanf("%d%d", &u, &v);
186         g[u].push_back(v);
187         g[v].push_back(u);
188     }
189     v = new ll[(n + 2)];
190     for (int i = 1; i <= n; i++)
191         scanf(Auto, v + i);
192 }
193 
194 ll A = 1, B;
195 int *a, *b;
196 
197 inline void discrete() {
198     vector<ll> _fac;
199     get_primary_factors(v[1], _fac);
200     factor fac = get_primary_factor(_fac);
201 
202     random_shuffle(fac.begin(), fac.end());
203     
204     a = new int[(n + 1)];
205     b = new int[(n + 1)];
206     ll da = 1, db = 1;
207     for (auto p : fac)
208         db *= (p.second + 1);
209     for (auto p : fac) {
210 //        cerr << p.first << " " << p.second << '\n';
211         if (da * (p.second + 1) <= db / (p.second + 1)) {
212             da *= (p.second + 1), db /= (p.second + 1);
213             for (int j = 0; j < p.second; j++)
214                 A *= p.first;
215         }
216     }
217     B = v[1] / A;
218 //    cerr << da << " " << db << '\n';
219 
220     for (int i = 1; i <= n; i++)
221         va.push_back(gcd(v[i], A));
222     for (int i = 1; i <= n; i++)
223         vb.push_back(gcd(v[i], B));
224 
225     sort(va.begin(), va.end());
226     sort(vb.begin(), vb.end());
227     va.erase(unique(va.begin(), va.end()), va.end());
228     vb.erase(unique(vb.begin(), vb.end()), vb.end());
229 
230 //    cerr << va.size() << ' ' << vb.size() << '\n';
231     F = Matrix<int>(va.size(), vb.size());
232     pfill(F[0], F[va.size()], 0);
233     for (int i = 1; i <= n; i++) {
234         a[i] = lower_bound(va.begin(), va.end(), gcd(v[i], A)) - va.begin();
235         b[i] = lower_bound(vb.begin(), vb.end(), gcd(v[i], B)) - vb.begin();
236     }
237 
238     diva = new vector<int>[va.size()];
239     divb = new vector<int>[vb.size()];
240     mula = new vector<int>[va.size()];
241     mulb = new vector<int>[vb.size()];
242     for (int i = 0; i < (signed) va.size(); i++) {
243         for (int j = 0; j < (signed) va.size(); j++) {
244             if (!(va[i] % va[j]))
245                 diva[i].push_back(j);
246             if (!(va[j] % va[i]))
247                 mula[i].push_back(j);
248         }
249     }
250     for (int i = 0; i < (signed) vb.size(); i++) {
251         for (int j = 0; j < (signed) vb.size(); j++) {
252             if (!(vb[i] % vb[j]))
253                 divb[i].push_back(j);
254             if (!(vb[j] % vb[i]))
255                 mulb[i].push_back(j);
256         }
257     }
258 }
259 
260 void dp(int p, int fa) {
261     if (p == 1) {
262         f[p] = 1;
263     } else {
264         for (auto x : mulb[b[p]])
265             f[p] = add(f[p], F[a[p]][x], Mod);
266     }
267     for (auto x : diva[a[p]])
268         F[x][b[p]] = add(F[x][b[p]], f[p], Mod);
269     for (auto e : g[p])
270         if (e ^ fa)
271             dp(e, p);
272     for (auto x : diva[a[p]])
273         F[x][b[p]] = sub(F[x][b[p]], f[p], Mod);
274 }
275 
276 inline void solve() {
277     f = new int[(n + 1)];
278     pfill(f + 1, f + n + 1, 0);
279     dp(1, 0);
280     for (int i = 1; i <= n; i++)
281         printf("%d\n", f[i]);
282 }
283 
284 int main() {
285     srand((unsigned) time (NULL));
286     init();
287     discrete();
288     solve();
289     return 0;
290 }
Problem A

Problem B 走路

  显然,使得$(1, 1)$和$(n, n)$不连通的方案斜着放车。

  然后随便容斥一下,得到:

$ans = n! - 2\sum_{i = 1}^{n}(n - i)! + 1 + \sum_{s = 2}^{n}(s - 1)(n - s)!$

  发现需要阶乘,阶乘的前缀和以及阶乘的前缀和前缀和。

  不会。分块大表。

  laofu把数压成若干可见字符的方法真高级。

  (请手动打表)

Code

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 typedef bool boolean;
 5 
 6 const int n = 1e7, Mod = 1e9 + 7;
 7 
 8 int add(int a, int b) {
 9     return ((a += b) >= Mod) ? (a - Mod) : (a);
10 }
11 
12 int sub(int a, int b) {
13     return ((a -= b) < 0) ? (a + Mod) : (a);
14 }
15 
16 int mul(int a, int b) {
17     return (a * 1ll * b) % Mod;
18 }
19 
20 void exgcd(int a, int b, int& x, int& y) {
21     if (!b)
22         x = 1, y = 0;
23     else {
24         exgcd(b, a % b, y, x);
25         y -= (a / b) * x;
26     }
27 }
28 
29 int inv(int a, int n) {
30     int x, y;
31     exgcd(a, n, x, y);
32     return (x < 0) ? (x + n) : (x);
33 }
34 
35 int fac[n + 1];
36 int sfac[n + 1];
37 int ssfac[n + 1];
38 int ans[n + 1];
39 
40 inline void init() {
41     fac[0] = 1;
42     for (int i = 1; i <= n; i++)
43         fac[i] = mul(fac[i - 1], i);
44     sfac[0] = 1;
45     for (int i = 1; i <= n; i++)
46         sfac[i] = add(sfac[i - 1], fac[i]);
47     ssfac[0] = 1;
48     for (int i = 1; i <= n; i++)
49         ssfac[i] = add(ssfac[i - 1], sfac[i]);
50 //    ans[1] = ans[2] = 0, ans[3] = 2;
51 //    int reduce = 
52 //    for (in ti = 4; i <= n; i++) {
53 //        ans[i] = add(ans[i - 1], fac[i]);
54 //        ans[i] = sub(ans[i], fac[i - 1]);
55 //        ans[i] = sub(ans[i], mul(fac[i - 1], 2));
56 //        ans[i] = add(ans[i], )
57 //    }
58 }
59 
60 inline void solve() {
61     int T, n;
62 //    cerr << fac[300000] << " " << sfac[300000] << " " << ssfac[300000] << '\n';
63     scanf("%d", &T);
64     while (T--) {
65         scanf("%d", &n);
66 //        int ans = fac[n];
67 //        for (int i = 1; i <= n; i++)
68 //            ans = sub(sub(ans, fac[n - i]), fac[n - i]);
69 //        ans = add(ans, 1);
70 //        for (int s = 2; s <= n; s++)
71 //            ans = add(ans, mul(s - 1, fac[n - s]));
72         int ans = ((n <= 2) ? 0 : add(fac[n], 1));
73         if (n > 2) {
74             ans = sub(ans, mul(sfac[n - 1], 2));
75             ans = add(ans, ssfac[n - 2]);
76         }
77         printf("%d\n", ans);
78     }
79 }
80 
81 int main() {
82     init();
83     solve();
84     return 0;
85 }
Problem B

Problem C 有趣的字符串题

  好像SD有道是这道题的强制在线的版本,之前有人讲过分块做法。然后就一直陷入了分块的漩涡中。sad....

  正解是考虑右端点在$r$的时候,询问左端点在每个位置时的答案。

  考虑移动右端点至$r + 1$时产生的贡献。显然我们只用考虑它的回文border。

  考虑一些长度构成等差数列的border。

  对于每一段讨论它会产生贡献的部分。注意向前移动周期个字符的情形以及前一个这中间的最长串的前一个的出现的位置$[x, y]$。

  若$z$是这些串中最短的一个串出现的左端点。不难得到当左端点在整数区间$(x, z]$中时,会有贡献。

  对于不同的这样的border,显然每一组可以单独计算贡献。

  因此我们用一个树状数组维护这个贡献,用线段树维护最后的出现位置,再用回文树维护border,就完事了。

  时间复杂度$O(n\log^2n + m\log n)$。

Code

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <map>
  7 using namespace std;
  8 typedef bool boolean;
  9 
 10 template <typename T>
 11 void pfill(T* pst, const T* ped, T val) {
 12     for ( ; pst != ped; *(pst++) = val);
 13 }
 14 
 15 typedef class Input {
 16     protected:
 17         const static int limit = 65536;
 18         FILE* file; 
 19 
 20         int ss, st;
 21         char buf[limit];
 22     public:
 23         
 24         Input():file(NULL)    {    };
 25         Input(FILE* file):file(file) {    }
 26 
 27         void open(FILE *file) {
 28             this->file = file;
 29         }
 30 
 31         void open(const char* filename) {
 32             file = fopen(filename, "r");
 33         }
 34 
 35         char pick() {
 36             if (ss == st)
 37                 st = fread(buf, 1, limit, file), ss = 0;//, cerr << "str: " << buf << "ed " << st << endl;
 38             return buf[ss++];
 39         }
 40 }Input;
 41 
 42 #define digit(_x) ((_x) >= '0' && (_x) <= '9')
 43 
 44 Input& operator >> (Input& in, unsigned& u) {
 45     char x;
 46     while (~(x = in.pick()) && !digit(x));
 47     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
 48     return in;
 49 }
 50 
 51 Input& operator >> (Input& in, unsigned long long& u) {
 52     char x;
 53     while (~(x = in.pick()) && !digit(x));
 54     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
 55     return in;
 56 }
 57 
 58 Input& operator >> (Input& in, int& u) {
 59     char x;
 60     while (~(x = in.pick()) && !digit(x) && x != '-');
 61     int aflag = ((x == '-') ? (x = in.pick(), -1) : (1));
 62     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
 63     u *= aflag;
 64     return in;
 65 }
 66 
 67 Input& operator >> (Input& in, long long& u) {
 68     char x;
 69     while (~(x = in.pick()) && !digit(x) && x != '-');
 70     int aflag = ((x == '-') ? (x = in.pick(), -1) : (1));
 71     for (u = x - '0'; ~(x = in.pick()) && digit(x); u = u * 10 + x - '0');
 72     u *= aflag;
 73     return in;
 74 }
 75 
 76 Input& operator >> (Input& in, char* str) {
 77     for (char x; ~(x = in.pick()) && x != '\n' && x != ' '; *(str++) = x);
 78 }
 79 
 80 Input in (stdin);
 81 
 82 const int alpha = 26;
 83 
 84 typedef class TrieNode {
 85     public:
 86         int len, dif, g;
 87         int in, out, id;
 88         map<char, TrieNode*> ch;
 89         TrieNode *fail, *slink;
 90 }TrieNode;
 91 
 92 typedef class PalindromeTree {
 93     public:
 94         int len;
 95         TrieNode *pool;
 96         TrieNode *top;
 97         TrieNode *odd, *even;
 98         TrieNode *last;
 99         TrieNode **node;
100         char *str; 
101 
102         TrieNode* newnode(int len) {
103             top->id = top - pool;
104             top->len = len, top->dif = -1, top->g = 0;
105 //            memset(top->ch, 0, sizeof(top->ch));
106             top->fail = top->slink = NULL;
107             return top++;
108         }
109 
110         PalindromeTree() {        }
111         PalindromeTree(int n) {
112             node = new TrieNode*[(n + 5)];
113             pool = new TrieNode[(n + 5)];
114             str = new char[(n + 5)];
115             top = pool, len = 0;
116             odd = newnode(-1), even = newnode(0);
117             odd->fail = odd, even->fail = odd;
118             odd->dif = even->dif = -1, last = even, str[0] = 0;
119         }
120 
121         TrieNode* extend(TrieNode* p) {
122             while (str[len - p->len - 1] != str[len])    p = p->fail;
123             return p;
124         }
125 
126         void append(char x) {
127             str[++len] = x;
128             int c = x - 'a';
129             last = extend(last);
130             if (!last->ch[c]) {
131                 TrieNode* p = newnode(last->len + 2);
132                 p->fail = extend(last->fail)->ch[c];
133                 if (!p->fail)
134                     p->fail = even;
135                 last->ch[c] = p;
136                 p->dif = p->len - p->fail->len; 
137 
138                 if (p->dif == p->fail->dif)
139                     p->slink = p->fail->slink;
140                 else
141                     p->slink = p->fail;
142             }
143             last = last->ch[c];
144             node[len] = last;
145         }
146 
147         void build(vector<int>* g) {
148             for (TrieNode* p = pool; p != top; p++) {
149                 if (p->fail && p->fail != p) {
150                     g[p->fail->id].push_back(p->id);
151                     g[p->id].push_back(p->fail->id);
152                 }
153             }
154         }
155 
156         TrieNode* operator [] (int p) {
157             return node[p];
158         }
159 }PalindromeTree;
160 
161 typedef class Query {
162     public:
163         int l, r, id;
164         
165         boolean operator < (Query p) const {
166             return r < p.r;
167         }
168 }Query;
169 
170 typedef class SegTreeNode {
171     public:
172         int val;
173         SegTreeNode *l, *r;
174 
175         SegTreeNode() : val(0), l(NULL), r(NULL) {    }
176 
177         void pushUp() {
178             val = max(l->val, r->val);
179         }
180 }SegTreeNode;
181 
182 const int N = 3e5 + 5;
183 
184 SegTreeNode pool[N << 2];
185 SegTreeNode *top = pool;
186 
187 SegTreeNode *newnode() {
188     return top++;
189 }
190 
191 typedef class SegTree {
192     public:
193         int n;
194         SegTreeNode* rt;
195 
196         SegTree() : rt(NULL) {    }
197         SegTree(int n) : n(n) {
198             build(rt, 1, n);
199         }
200 
201         void build(SegTreeNode*& p, int l, int r) {
202             p = newnode();
203             if (l == r)
204                 return ;
205             int mid = (l + r) >> 1;
206             build(p->l, l, mid);
207             build(p->r, mid + 1, r);
208         }
209 
210         void modify(SegTreeNode *p, int l, int r, int idx, int val) {
211             if (l == r) {
212                 p->val = val;
213                 return ;    
214             }
215             int mid = (l + r) >> 1;
216             if (idx <= mid)
217                 modify(p->l, l, mid, idx, val);
218             else
219                 modify(p->r, mid + 1, r, idx, val);
220             p->pushUp();
221         }
222 
223         int query(SegTreeNode* p, int l, int r, int ql, int qr) {
224             if (l == ql && r == qr)
225                 return p->val;
226             int mid = (l + r) >> 1;
227             if (qr <= mid)
228                 return query(p->l, l, mid, ql, qr);
229             if (ql > mid)
230                 return query(p->r, mid + 1, r, ql, qr);
231             int a = query(p->l, l, mid, ql, mid);
232             int b = query(p->r, mid + 1, r, mid + 1, qr);
233             return (a > b) ? (a) : (b);
234         }
235 
236         void modify(int idx, int val) {
237             modify(rt, 1, n, idx, val);
238         }
239 
240         int query(int ql, int qr) {
241             return query(rt, 1, n, ql, qr);
242         }
243 }SegTree;
244 
245 typedef class IndexedTree {
246     public:
247         int s;
248         int *a;
249 
250         IndexedTree() {    }
251         IndexedTree(int n) : s(n) {
252             a = new int[(n + 1)];
253             pfill(a, a + n + 1, 0);
254         }
255 
256         void add(int idx, int val) {
257             for ( ; idx <= s; idx += (idx & (-idx)))
258                 a[idx] += val;
259         }
260 
261         void add(int l, int r, int val) {
262             add(l, val), add(r + 1, -val);
263         }
264 
265         int query(int idx) {
266             int rt = 0;
267             for ( ; idx; idx -= (idx & (-idx)))
268                 rt += a[idx];
269             return rt;
270         }
271 }IndexedTree;
272 
273 const int Mod = 1e9 + 7;
274 
275 int add(int a, int b) {
276     return ((a += b) >= Mod) ? (a - Mod) : (a);
277 }
278 
279 int sub(int a, int b) {
280     return ((a -= b) < 0) ? (a + Mod) : (a);
281 }
282 
283 int mul(int a, int b) {
284     return a * 1ll * b % Mod;
285 }
286 
287 int n, m;
288 char *s;
289 Query* qs;
290 SegTree st;
291 vector<int> *g;
292 IndexedTree it;
293 PalindromeTree pt;
294 
295 inline void init() {
296     in >> n >> m;
297     s = new char[(n + 5)];
298     qs = new Query[(m + 1)];
299     pt = PalindromeTree(n + 5);
300     g = new vector<int>[(n + 5)];
301     in >> s;
302     for (int i = 0; i < n; i++)
303         pt.append(s[i]);
304     delete[] s;
305     pt.build(g);
306     for (int i = 1; i <= m; i++)
307         in >> qs[i].l >> qs[i].r, qs[i].id = i;
308 }
309 
310 int dfs_clock;
311 void dfs(int p, int fa) {
312     pt.pool[p].in = ++dfs_clock;
313 //    cerr << p << " " << fa << '\n';
314     for (auto e : g[p])
315         if (e ^ fa)
316             dfs(e, p);
317     pt.pool[p].out = dfs_clock;
318 }
319 
320 int res = 0;
321 inline void solve() {
322     st = SegTree(n + 3);
323     it = IndexedTree(n);
324     dfs(0, -1);
325     sort(qs + 1, qs + m + 1);
326     
327     Query* q = qs + 1, *qed = qs + m + 1;
328     for (int i = 1; i <= n; i++) {
329         for (TrieNode *p = pt[i]; p && p->len; p = p->slink) {
330             int left = max(st.query(p->in, p->out) - p->len + 1, 0) + 1;
331             int right = i - p->dif - ((p->slink) ? (p->slink->len) : (0)) + 1;            
332 //            cerr << i << " " << left << " " << right << '\n';
333             it.add(left, right, 1);
334         }
335         st.modify(pt[i]->in, i);
336         while (q != qed && q->r == i) {
337             res = add(res, mul(it.query(q->l), q->id));
338 //            cerr << "Q: " << it.query(q->l) << " " << q->id << '\n';
339             q++;
340         }
341     }
342     printf("%d\n", res);
343 }
344 
345 int main() {
346     init();
347     solve();
348     return 0;
349 }
Problem C
posted @ 2018-11-29 21:29  阿波罗2003  阅读(435)  评论(0编辑  收藏  举报