2018 Multi-University Training Contest 2
UPD:艰难补完了感觉有几个题好像没什么人写还是简单讲两句吧
1001 Absolute
快乐积分每一天
好像大家都是不定积分的但是因为我比较傻逼不会那种容斥一样的东西所以考虑写一个定积分
假设前$i$个区间的概率密度函数积出来是一个分段函数$g(x)$,第$i + 1$个区间是一个水平线,记为$h(x) = [hl \leq x \leq hr] \cdot \frac{1}{hr - hl}$
那么合并出来的概率密度函数$f(x) = \sum_{i} \int _{gl[i]} ^{gr[i]} g(y) h(x - y) dy$,考虑一下$h(x - y)$不为$0$时候的条件$hl \leq x - y \leq hr$,这个和$x$有关
于是要考虑$x - hl$, $x - hr$与$gl$, $gr$的大小关系,将$f(x)$分三段积分,$x$在这三段中的积分上下界是不同的
分段的端点是$gl + hl$, $gl + hr$, $gr + gl$, $gr + hr$,但是$gl + hr$和$gr + gl$大小关系无法确定,这里就要分类讨论了
考虑$gl + hr < gr + gl$的情况,第一段当$x \in [gl + hl, gl + hr]$时,考虑$hl \leq x - y \leq hr$的条件,由于$x \leq gl + hr$,所以$x - y \leq hr$肯定满足了
但是$hl \leq x - y$不一定满足,所以积分区间要加上$y \leq x - hl$的条件,这一段写出来就是$\int _{gl[i]} ^{x - hl} g(y) \frac{1}{hr - hl} dy$
其他两端和另一种情况的三段也类似的写,积分上下界只有$gl$, $gr$, $x - hl$, $x - hr$这四种,对于数值直接带进去$O(n)$就完了
对于$x - hl$这种形式,积出来还是一个多项式,带入$y = x - hl$的时候用二项展开$O(n^2)$算完,这只是一个$n = 15$的孩子不能随便用$fft$艹它吧?
式子推完大概也能理解不定积分的写法了,就是考虑每个段点究竟是积分的上界还是下界
定积分的写法好像$L = R$的情况要单独搞搞?虽然数据贼弱没有这种
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int mod = 998244353; 5 int hl[22], hr[22], C[22][22]; 6 int p[2][1<<16][17], t1[17], t2[17]; 7 vector<int> b[2]; 8 9 LL fp(LL a, LL b) { 10 LL ret = 1; 11 while (b) { 12 if (b & 1) ret = ret * a % mod; 13 a = a * a % mod; 14 b >>= 1; 15 } 16 return ret; 17 } 18 LL inv(LL x) { 19 return fp(x, mod - 2); 20 } 21 22 inline void INT(int *p) { 23 for (int i = 16; i >= 1; --i) p[i] = p[i - 1] * inv(i) % mod; 24 p[0] = 0; 25 } 26 inline void VAL(int *p, int x, int *ret) { 27 LL t = 0, base = 1; 28 for (int i = 0; i < 17; ++i) { 29 t = (t + base * p[i]) % mod; 30 base = base * x % mod; 31 } 32 for (int i = 1; i < 17; ++i) ret[i] = 0; 33 ret[0] = t; 34 } 35 inline void XVAL(int *p, int x, int *ret) { 36 for (int i = 0; i < 17; ++i) ret[i] = 0; 37 for (int i = 0; i < 17; ++i) 38 for (int j = 0; j <= i; ++j) 39 ret[i - j] = (ret[i - j] + (LL) p[i] * fp(x, j) % mod * C[i][j]) % mod; 40 } 41 inline void ADD(int *a, int *b) { 42 for(int i = 0; i < 17; ++i) a[i] = (a[i] + b[i]) % mod; 43 } 44 inline void SUB(int *a, int *b) { 45 for(int i = 0; i < 17; ++i) a[i] = (a[i] + mod - b[i]) % mod; 46 } 47 inline void MUL(int * a, int b) { 48 for(int i = 0; i < 17; ++i) a[i] = (a[i] * (LL) b) % mod; 49 } 50 51 int main() { 52 for(int i = 0; i < 22; ++i) C[i][0] = C[i][i] = 1; 53 for(int i = 2; i < 22; ++i) 54 for(int j = 1; j < i; ++j) 55 C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod; 56 int n, bias = 0, o = 0; 57 scanf("%d", &n); 58 for(int i = 1; i <= n; ++i) { 59 scanf("%d %d", hl + i, hr + i); 60 if(hl[i] == hr[i]) bias += hl[i], i--, n--; 61 } 62 if(n == 0) { 63 printf("%d\n", abs(bias)); 64 return 0; 65 } 66 b[o].push_back(hl[1]), b[o].push_back(hr[1]); 67 p[o][0][0] = inv(hr[1] - hl[1]); 68 for(int i = 2; i <= n; ++i) { 69 int x = inv(hr[i] - hl[i]); 70 b[o^1].clear(); 71 for(int j = 0; j < 2 * b[o].size(); ++j) memset(p[o^1][j], 0, sizeof(p[o^1][j])); 72 for(int j = 0; j < b[o].size(); ++j) b[o^1].push_back(b[o][j] + hl[i]), b[o^1].push_back(b[o][j] + hr[i]); 73 sort(b[o^1].begin(), b[o^1].end()); 74 b[o^1].erase(unique(b[o^1].begin(), b[o^1].end()), b[o^1].end()); 75 for(int j = 0; j < b[o].size() - 1; ++j) { 76 INT(p[o][j]); 77 int gl = b[o][j], gr = b[o][j + 1], ngl, ngr; 78 if(gl + hr[i] < gr + hl[i]) { 79 // [gl + hl, gl + hr] 80 ngl = lower_bound(b[o^1].begin(), b[o^1].end(), gl + hl[i]) - b[o^1].begin(); 81 ngr = lower_bound(b[o^1].begin(), b[o^1].end(), gl + hr[i]) - b[o^1].begin(); 82 XVAL(p[o][j], mod - hl[i], t1), VAL(p[o][j], mod + gl, t2); 83 SUB(t1, t2), MUL(t1, x), ADD(p[o^1][ngl], t1), SUB(p[o^1][ngr], t1); 84 // [gl + hr, gr + hl] 85 ngl = lower_bound(b[o^1].begin(), b[o^1].end(), gl + hr[i]) - b[o^1].begin(); 86 ngr = lower_bound(b[o^1].begin(), b[o^1].end(), gr + hl[i]) - b[o^1].begin(); 87 XVAL(p[o][j], mod - hl[i], t1), XVAL(p[o][j], mod - hr[i], t2); 88 SUB(t1, t2), MUL(t1, x), ADD(p[o^1][ngl], t1), SUB(p[o^1][ngr], t1); 89 // [gr + hl, gr + hr] 90 ngl = lower_bound(b[o^1].begin(), b[o^1].end(), gr + hl[i]) - b[o^1].begin(); 91 ngr = lower_bound(b[o^1].begin(), b[o^1].end(), gr + hr[i]) - b[o^1].begin(); 92 VAL(p[o][j], mod + gr, t1), XVAL(p[o][j], mod - hr[i], t2); 93 SUB(t1, t2), MUL(t1, x), ADD(p[o^1][ngl], t1), SUB(p[o^1][ngr], t1); 94 } 95 else { 96 // [gl + hl, gr + hl] 97 ngl = lower_bound(b[o^1].begin(), b[o^1].end(), gl + hl[i]) - b[o^1].begin(); 98 ngr = lower_bound(b[o^1].begin(), b[o^1].end(), gr + hl[i]) - b[o^1].begin(); 99 XVAL(p[o][j], mod - hl[i], t1), VAL(p[o][j], mod + gl, t2); 100 SUB(t1, t2), MUL(t1, x), ADD(p[o^1][ngl], t1), SUB(p[o^1][ngr], t1); 101 // [gr + hl, gl + hr] 102 ngl = lower_bound(b[o^1].begin(), b[o^1].end(), gr + hl[i]) - b[o^1].begin(); 103 ngr = lower_bound(b[o^1].begin(), b[o^1].end(), gl + hr[i]) - b[o^1].begin(); 104 VAL(p[o][j], mod + gr, t1), VAL(p[o][j], mod + gl, t2); 105 SUB(t1, t2), MUL(t1, x), ADD(p[o^1][ngl], t1), SUB(p[o^1][ngr], t1); 106 // [gl + hr, gr + hr] 107 ngl = lower_bound(b[o^1].begin(), b[o^1].end(), gl + hr[i]) - b[o^1].begin(); 108 ngr = lower_bound(b[o^1].begin(), b[o^1].end(), gr + hr[i]) - b[o^1].begin(); 109 VAL(p[o][j], mod + gr, t1), XVAL(p[o][j], mod - hr[i], t2); 110 SUB(t1, t2), MUL(t1, x), ADD(p[o^1][ngl], t1), SUB(p[o^1][ngr], t1); 111 } 112 } 113 for(int j = 1; j < b[o^1].size() - 1; ++j) ADD(p[o^1][j], p[o^1][j - 1]); 114 o ^= 1; 115 } 116 LL ans = 0; 117 for(int i = 0; i < b[o].size() - 1; ++i) { 118 int gl = b[o][i] + bias, gr = b[o][i + 1] + bias; 119 XVAL(p[o][i], mod - bias, t1); 120 for(int j = 16; j > 0; --j) t1[j] = t1[j - 1]; 121 t1[0] = 0, INT(t1); 122 if(gl <= 0 && gr >= 0) { 123 VAL(t1, gr, t2), ans += t2[0]; 124 VAL(t1, gl, t2), ans += t2[0]; 125 VAL(t1, 0, t2), ans += 2 * (mod - t2[0]); 126 } 127 else if(gr <= 0) { 128 VAL(t1, gl, t2), ans += t2[0]; 129 VAL(t1, gr, t2), ans += (mod - t2[0]); 130 } 131 else { 132 VAL(t1, gr, t2), ans += t2[0]; 133 VAL(t1, gl, t2), ans += (mod - t2[0]); 134 } 135 } 136 printf("%lld\n", ans % mod); 137 return 0; 138 }
考虑用多项式表示答案$h_{n} = \sum_{p} x^{\sum_{i} \min (i - l_{i}, r_{i} - i)}$,就有递推式$h_{n} = \sum_{i = 1} ^{n} x^{min(i, n + 1 - i)}h_{i - 1} h_{n - i}C_{n}^{i - 1}$
这个多项式的最高次也就是$\sum_{i} \min (i - l_{i}, r_{i} - i)$的最大值是$g_{n} = O(nlogn)$级别的打表出来$g_{200} = 735$,所以暴力推这个多项式是$O(n^{4}log^{2}n)$
优化就是不算多项式算点值,这只用$O(n^{3}logn)$,每次询问的时候拿拉格朗日把系数插出来,单次是$O(n^2log^2n)$
拉格朗日系数表示要先算一下分子多项式,预处理分母阶乘,然后每次分子除一个一次式,这样就是是次数平方的
标算卡不过阿???
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 int mod, g[222], h[222][777], inv_fac[777], C[222][222], po[777][222]; 5 6 int a[777], b[777], c[777], d[777]; 7 int solve(int n, int x) { 8 if(x > g[n]) return 0; 9 for(int i = 0; i <= g[n]; ++i) a[i] = 0, b[i] = 0; 10 b[0] = 1; 11 for(int i = 0; i <= g[n]; ++i) { 12 for(int j = i + 1; j > 0; --j) b[j] = b[j - 1]; 13 b[0] = 0; 14 for(int j = 0; j <= i; ++j) b[j] = (b[j] + (LL) (mod - i) * b[j + 1]) % mod; 15 } 16 for(int i = 0; i <= g[n]; ++i) { 17 for(int j = g[n]; j >= 0; --j) c[j] = 0; 18 for(int j = 0; j <= g[n] + 1; ++j) d[j] = b[j]; 19 for(int j = g[n]; j >= 0; --j) { 20 c[j] = d[j + 1]; 21 d[j] = (d[j] + (LL) i * c[j]) % mod; 22 } 23 assert(d[0] == 0); 24 int y = (LL) inv_fac[i] * inv_fac[g[n] - i] % mod * h[n][i] % mod; 25 if((g[n] - i) % 2) y = mod - y; 26 for(int j = 0; j <= g[n]; ++j) a[j] = (a[j] + (LL) y * c[j]) % mod; 27 } 28 return a[x]; 29 } 30 31 int main() { 32 for(int i = 1; i <= 200; ++i) 33 for(int j = 1; j <= i; ++j) 34 g[i] = max(g[i], g[j - 1] + g[i - j] + min(j, i - j + 1)); 35 scanf("%d", &mod); 36 inv_fac[0] = inv_fac[1] = 1; 37 for(int i = 2; i <= g[200]; ++i) inv_fac[i] = (LL) (mod - mod / i) * inv_fac[mod % i] % mod; 38 for(int i = 3; i <= g[200]; ++i) inv_fac[i] = (LL) inv_fac[i] * inv_fac[i - 1] % mod; 39 for(int i = 0; i <= 200; ++i) C[i][0] = C[i][i] = 1; 40 for(int i = 2; i <= 200; ++i) 41 for(int j = 1; j < i; ++j) 42 C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod; 43 for(int i = 1; i <= g[200]; ++i) { 44 po[i][0] = 1; 45 for(int j = 1; j <= 200; ++j) po[i][j] = (LL) po[i][j - 1] * i % mod; 46 } 47 for(int i = 0; i <= g[200]; ++i) h[0][i] = 1; 48 for(int i = 1; i <= 200; ++i) 49 for(int j = 1; j <= g[200]; ++j) 50 for(int k = 1; k <= i; ++k) 51 h[i][j] = (h[i][j] + (LL) po[j][min(k, i - k + 1)] * h[k - 1][j] % mod * h[i - k][j] % mod * C[i - 1][k - 1]) % mod; 52 int n, x; 53 while(~scanf("%d %d", &n, &x)) printf("%d\n", solve(n, x)); 54 return 0; 55 }
UPD:看了下dls的暴力真香发现对称的部分可以只枚举一半终于卡过了
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 int mod, g[222], h[222][777], inv_fac[777], C[222][222], po[777][222]; 5 6 int a[777], b[777], c[777], d[777]; 7 int solve(int n, int x) { 8 if(x > g[n]) return 0; 9 for(int i = 0; i <= g[n]; ++i) a[i] = 0, b[i] = 0; 10 b[0] = 1; 11 for(int i = 0; i <= g[n]; ++i) { 12 for(int j = i + 1; j > 0; --j) b[j] = b[j - 1]; 13 b[0] = 0; 14 for(int j = 0; j <= i; ++j) b[j] = (b[j] + (LL) (mod - i) * b[j + 1]) % mod; 15 } 16 for(int i = 0; i <= g[n]; ++i) { 17 for(int j = g[n]; j >= 0; --j) c[j] = 0; 18 for(int j = 0; j <= g[n] + 1; ++j) d[j] = b[j]; 19 for(int j = g[n]; j >= 0; --j) { 20 c[j] = d[j + 1]; 21 d[j] = (d[j] + (LL) i * c[j]) % mod; 22 } 23 assert(d[0] == 0); 24 int y = (LL) inv_fac[i] * inv_fac[g[n] - i] % mod * h[n][i] % mod; 25 if((g[n] - i) % 2) y = mod - y; 26 for(int j = 0; j <= g[n]; ++j) a[j] = (a[j] + (LL) y * c[j]) % mod; 27 } 28 return a[x]; 29 } 30 31 int main() { 32 for(int i = 1; i <= 200; ++i) 33 for(int j = 1; j <= i; ++j) 34 g[i] = max(g[i], g[j - 1] + g[i - j] + min(j, i - j + 1)); 35 scanf("%d", &mod); 36 inv_fac[0] = inv_fac[1] = 1; 37 for(int i = 2; i <= g[200]; ++i) inv_fac[i] = (LL) (mod - mod / i) * inv_fac[mod % i] % mod; 38 for(int i = 3; i <= g[200]; ++i) inv_fac[i] = (LL) inv_fac[i] * inv_fac[i - 1] % mod; 39 for(int i = 0; i <= 200; ++i) C[i][0] = C[i][i] = 1; 40 for(int i = 2; i <= 200; ++i) 41 for(int j = 1; j < i; ++j) 42 C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod; 43 for(int i = 1; i <= g[200]; ++i) { 44 po[i][0] = 1; 45 for(int j = 1; j <= 200; ++j) po[i][j] = (LL) po[i][j - 1] * i % mod; 46 } 47 for(int i = 0; i <= g[200]; ++i) h[0][i] = 1; 48 for(int i = 1; i <= 200; ++i) { 49 for(int j = 1; j <= g[200]; ++j) { 50 for(int k = 1; k <= i; ++k) { 51 int l = k - 1, r = i - k, c = 1; 52 if(l > r) break; 53 if(l != r) c++; 54 h[i][j] = (h[i][j] + (LL) c * po[j][min(k, i - k + 1)] * h[k - 1][j] % mod * h[i - k][j] % mod * C[i - 1][k - 1]) % mod; 55 } 56 } 57 } 58 int n, x; 59 while(~scanf("%d %d", &n, &x)) printf("%d\n", solve(n, x)); 60 return 0; 61 }
1003 Cover
被教了一下午欧拉回路最后忘记判孤立点了……
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 4e5 + 10; 4 int u[maxn], v[maxn], vis[maxn]; 5 vector<int> G[maxn]; 6 vector< vector<int> > ans; 7 vector<int> tmp, node, o; 8 9 void dfs1(int x) { 10 vis[x] = 1; 11 if(G[x].size() % 2 == 1) node.push_back(x); 12 for(int i = 0; i < G[x].size(); ++i) { 13 int eid = G[x][i], to = eid > 0 ? v[eid] : u[-eid]; 14 if(vis[to]) continue; 15 dfs1(to); 16 } 17 } 18 19 int e_vis[maxn]; 20 void dfs(int x) { 21 while(!G[x].empty()) { 22 int eid = G[x][G[x].size() - 1]; 23 while(e_vis[abs(eid)]) { 24 G[x].pop_back(); 25 if(G[x].empty()) return; 26 eid = G[x][G[x].size() - 1]; 27 } 28 int U = u[abs(eid)], V = v[abs(eid)]; 29 int nxt = eid > 0 ? V : U; 30 e_vis[abs(eid)] = 1; 31 dfs(nxt); 32 tmp.push_back(eid); 33 } 34 } 35 36 int main() { 37 int n, m; 38 while(~scanf("%d %d", &n, &m)) { 39 for(int i = 1; i <= n; ++i) G[i].clear(), vis[i] = 0; 40 for(int i = 1; i <= m; ++i) { 41 e_vis[i] = 0; 42 scanf("%d %d", u + i, v + i); 43 G[u[i]].push_back(i); 44 G[v[i]].push_back(-i); 45 } 46 int add = 0; 47 ans.clear(); 48 for(int i = 1; i <= n; ++i) { 49 if(vis[i]) continue; 50 node.clear(), dfs1(i); 51 for(int j = 0; j < node.size(); j += 2) { 52 int eid = m + (++add); 53 e_vis[eid] = 0; 54 u[eid] = node[j], v[eid] = node[j+1]; 55 G[node[j]].push_back(eid); 56 G[node[j+1]].push_back(-eid); 57 } 58 tmp.clear(), dfs(i); 59 if(tmp.empty()) continue; 60 if(node.empty()) ans.push_back(tmp); 61 else { 62 int st = 0; 63 while(abs(tmp[st]) <= m) st++; 64 st++; 65 for(int j = 0; j < tmp.size(); ++j) { 66 o.clear(); 67 int k = j; 68 while(abs(tmp[(st + k) % tmp.size()]) <= m) k++; 69 for(int p = j; p < k; ++p) o.push_back(tmp[(p+st) % tmp.size()]); 70 ans.push_back(o); 71 j = k; 72 } 73 } 74 } 75 printf("%d\n", int(ans.size())); 76 for(int i = 0; i < ans.size(); ++i) { 77 printf("%d", (int) ans[i].size()); 78 reverse(ans[i].begin(), ans[i].end()); 79 for(int j = 0; j < ans[i].size(); ++j) 80 printf(" %d", ans[i][j]); 81 puts(""); 82 } 83 } 84 return 0; 85 }
1004 Game
取1换先后手
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() { 5 int n; 6 while(~scanf("%d", &n)) puts("Yes"); 7 return 0; 8 }
1005 Hack It
不会构造
1 #include<bits/stdc++.h> 2 using namespace std; 3 bool a[2304][2304]; 4 int main(){ 5 for(int i=1;i<=47;i++){ 6 for(int j=1;j<=47;j++){ 7 a[i][(i-1)*47+j]=true; 8 } 9 } 10 for(int i=0;i<=46;i++){ 11 for(int j=1;j<=47;j++){ 12 for(int k=0;k<=46;k++){ 13 a[(i+1)*47+j][k*47+(j+k*i-1)%47+1]=true; 14 } 15 } 16 } 17 puts("2000"); 18 for(int i=1;i<=2000;i++) 19 { 20 for(int j=1;j<=2000;j++) 21 if (a[i][j]) putchar('1'); else putchar('0'); 22 puts(""); 23 } 24 return 0; 25 }
1006 Matrix
打容斥系数表
为什么市面上都是dls推式子做法你们好强强阿QAQ
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int mod = 998244353; 4 int po[9000005], C[3005][3005], fa[3005], fb[3005]; 5 typedef long long LL; 6 7 int main() { 8 po[0] = 1; 9 for(int i = 1; i < 9000005; ++i) po[i] = (po[i-1] + po[i-1]) % mod; 10 for(int i = 0; i < 3005; ++i) C[i][0] = C[i][i] = 1; 11 for(int i = 2; i < 3005; ++i) 12 for(int j = 1; j < i; ++j) 13 C[i][j] = (C[i-1][j] + C[i-1][j-1]) % mod; 14 int n, m, A, B; 15 while(~scanf("%d %d %d %d", &n, &m, &A, &B)) { 16 for(int i = A; i <= n; ++i) { 17 fa[i] = 1; 18 for(int j = A; j < i; ++j) fa[i] = (fa[i] + mod - (LL) C[i][j] * fa[j] % mod) % mod; 19 } 20 for(int i = B; i <= m; ++i) { 21 fb[i] = 1; 22 for(int j = B; j < i; ++j) fb[i] = (fb[i] + mod - (LL) C[i][j] * fb[j] % mod) % mod; 23 } 24 int ans = 0; 25 for(int i = A; i <= n; ++i) 26 for(int j = B; j <= m; ++j) 27 ans = (ans + (LL) fa[i] * C[n][i] % mod * fb[j] % mod * C[m][j] % mod * po[(n-i)*(m-j)]) % mod; 28 printf("%d\n", ans); 29 } 30 return 0; 31 }
1007 Naive Operations
只在整数部分增加的时候递归子树仔细一想是两个log的
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1e5 + 10; 4 int b[maxn]; 5 6 int sum[maxn<<2], mi[maxn<<2], tag[maxn<<2]; 7 void gather(int p) { 8 sum[p] = sum[p << 1] + sum[p << 1 | 1]; 9 mi[p] = min(mi[p << 1], mi[p << 1 | 1]); 10 } 11 void push(int p) { 12 if (tag[p]) { 13 tag[p << 1] += tag[p]; 14 tag[p << 1 | 1] += tag[p]; 15 mi[p << 1] -= tag[p]; 16 mi[p << 1 | 1] -= tag[p]; 17 tag[p] = 0; 18 } 19 } 20 void build(int p, int l, int r) { 21 tag[p] = sum[p] = 0; 22 if (l < r) { 23 int mid = (l + r) >> 1; 24 build(p << 1, l, mid); 25 build(p << 1 | 1, mid + 1, r); 26 gather(p); 27 } else mi[p] = b[l]; 28 } 29 void modify(int p, int tl, int tr, int l, int r) { 30 if (tl > tr) return; 31 if (tr < l || r < tl) return; 32 if (l <= tl && tr <= r) { 33 if(tl == tr) { 34 mi[p]--, tag[p] = 0; 35 while(mi[p] <= 0) mi[p] += b[tl], sum[p]++; 36 return; 37 } 38 else if(mi[p] > 1) {tag[p]++, mi[p]--; return;} 39 } 40 push(p); 41 int mid = (tl + tr) >> 1; 42 modify(p << 1, tl, mid, l, r); 43 modify(p << 1 | 1, mid + 1, tr, l, r); 44 gather(p); 45 } 46 int query(int p, int tl, int tr, int l, int r) { 47 if (tl > tr) return 0; 48 if (tr < l || r < tl) return 0; 49 if (l <= tl && tr <= r) return sum[p]; 50 push(p); 51 int mid = (tl + tr) >> 1; 52 return query(p << 1, tl, mid, l, r) + query(p << 1 | 1, mid + 1, tr, l, r); 53 } 54 55 int main() { 56 int n, q; 57 while(~scanf("%d %d", &n, &q)) { 58 for(int i = 1; i <= n; ++i) scanf("%d", b + i); 59 build(1, 1, n); 60 while(q--) { 61 int l, r; 62 char s[11]; 63 scanf("%s %d %d", s, &l, &r); 64 if(s[0] == 'a') modify(1, 1, n, l, r); 65 else printf("%d\n", query(1, 1, n, l, r)); 66 } 67 } 68 return 0; 69 }
1008 Odd Shops
抄抄标程
考虑算$f(x)^{n}g(x)$的奇数项数目,对应原问题就是$g(x) = 1$
如果$n$为奇数可以拿一个$f(x)$到$g(x)$,于是一定可以变成$f(x)^{2k}g(x)$的形式
把$g(x)$的奇偶项拆开变成$g(x) = h(x) + r(x)$,那么$f(x)^{2k}h(x)$和$f(x)^{2k}r(x)$两边可以独立算
对于奇数项$f(x)^{2k}r(x)$这边,提出一个$x$是没有影响的,所以变为计算$f(x)^{2k}r ' (x)$,式中$r ' (x) \cdot x = r(x)$
问题变为计算$f(x)^{2k}h(x)$和$f(x)^{2k}r'(x)$两个偶次式的奇数项数目,因为模$2$意义下$f(x^2)^k = f(x)^{2k}$所以直接把所有指数折半就变成了子问题
整个过程都在递归,唯一的计算部分在做一次$f(x) \cdot g(x)$,因为$g(x)$每次乘个$f(x)$,又折半,所以永远最高是$10$次多项式,暴力,压位,预处理,都行
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int mod = 998244353; 4 typedef pair<int, int> pii; 5 map<pii, int> mp; 6 int msk; 7 8 int solve(int n, int g) { 9 if (n == 0) return __builtin_popcount(g); 10 if (mp.find({n, g}) != mp.end()) return mp[{n, g}]; 11 if (n & 1) { 12 int t = 0; 13 for (int i = 0; i <= 10; ++i) 14 if (msk & (1 << i)) t ^= g << i; 15 g = t; 16 } 17 int msko = 0, mske = 0; 18 for (int i = 0; i <= 20; ++i) { 19 if (g & (1 << i)) { 20 if (i & 1) msko |= (1 << (i / 2)); 21 else mske |= (1 << (i / 2)); 22 } 23 } 24 return mp[{n, g}] = solve(n / 2, msko) + solve(n / 2, mske); 25 } 26 27 int main() { 28 int n; 29 while (~scanf("%d", &n)) { 30 mp.clear(), msk = 1; 31 for (int i = 1; i <= 10; ++i) { 32 int x; 33 scanf("%x", &x); 34 msk |= (x % 2) << i; 35 } 36 printf("%d\n", solve(n, 1)); 37 } 38 return 0; 39 }
1009 Segment
先想怎么算贡献,首先对于与询问有交集的区间,都有有$+1$的贡献,但是父亲被整个包含的要去除,再给这些节点$-1$,由于这部分贡献算在自己身上不好处理,直接算到父亲上
考虑每个被完全包含的非叶节点,它作为父亲时有两个孩子会有$-1$的贡献算在它身上,所以每个被包含的非叶节点实际贡献是$+1 - 1 - 1 = -1$
总结起来就是,有交集不被包含$+1$,被包含非叶$-1$,被包含叶子$+1$
再考虑每个区间出现概率,直观感觉只和长度有关,打表出来发现包含$1$, $n$作为端点的是例外,证明我反正不懂
$P([1, n]) = 1$, $P([1, k < n]) = \frac{1}{k}$, $P([k > 1, n]) = \frac{1}{n - k + 1}$, $P([1 < l, r < n]) = \frac{2}{(r - l + 1)(r - l)} = 2(\frac{1}{r - l} - \frac{1}{r - l + 1})$快乐裂项好求和
对于每组询问,首先特判掉$[1, n]$,然后看是否包含$1$和$n$分两类,每类按端点讨论上述三种区间,都能变成调和级数区间和的形式,预处理逆元前缀和就好了
最后就是比谁的读入挂跑得快就牛逼阿?
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const LL mod = 998244353; 5 const int maxn = 1e6 + 10; 6 LL inv[maxn], sum[maxn]; 7 8 namespace fastIO{ 9 #define BUF_SIZE 100000 10 #define OUT_SIZE 100000 11 #define ll long long 12 //fread->read 13 bool IOerror=0; 14 inline char nc(){ 15 static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE; 16 if (p1==pend){ 17 p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin); 18 if (pend==p1){IOerror=1;return -1;} 19 //{printf("IO error!\n");system("pause");for (;;);exit(0);} 20 } 21 return *p1++; 22 } 23 inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';} 24 inline void read(int &x){ 25 bool sign=0; char ch=nc(); x=0; 26 for (;blank(ch);ch=nc()); 27 if (IOerror)return; 28 if (ch=='-')sign=1,ch=nc(); 29 for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; 30 if (sign)x=-x; 31 } 32 #undef ll 33 #undef OUT_SIZE 34 #undef BUF_SIZE 35 }; 36 using namespace fastIO; 37 38 int main() { 39 inv[1] = sum[1] = 1; 40 for(int i = 2; i < maxn; ++i) inv[i] = (mod - (mod / i)) * inv[mod % i] % mod; 41 for(int i = 2; i < maxn; ++i) sum[i] = (sum[i - 1] + inv[i]) % mod; 42 int n, q; 43 read(n), read(q); 44 while(q--) { 45 int l, r; 46 read(l), read(r); 47 if(l == 1 && r == n) {puts("1"); continue;} 48 if(r == n) r = n + 1 - l, l = 1; 49 LL intersect = 1, nonleaf = 0, leaf = r - l + 1; 50 if(l == 1) { 51 // [1, R + 1 ~ N - 1] 52 intersect = (intersect + sum[n - 1] - sum[r] + mod) % mod; 53 // [2 ~ R, R + 1 ~ N - 1] 54 intersect = (intersect + 2 * (sum[r] - sum[1] - sum[n - 1] + sum[n - r] + mod + mod)) % mod; 55 // [2 ~ R, N] 56 intersect = (intersect + sum[n - 1] - sum[n - r] + mod) % mod; 57 // [1, 2 ~ R] 58 nonleaf = (nonleaf + sum[r] - sum[1]) % mod; 59 // [2 ~ M, M ~ R] 60 nonleaf = (nonleaf + r - 2 + 2 * (sum[2] + mod - sum[r])) % mod; 61 } 62 else { 63 // [2 ~ L - 1, L ~ R] 64 intersect = (intersect + 2 * (sum[r - l + 2] - sum[1] - sum[r] + sum[l - 1] + mod + mod)) % mod; 65 // [L ~ R, R + 1 ~ N - 1] 66 intersect = (intersect + 2 * (sum[r - l + 2] - sum[1] - sum[n - l + 1] + sum[n - r] + mod + mod)) % mod; 67 // [2 ~ L - 1, R + 1 ~ N - 1] 68 intersect = (intersect + 2 * (sum[r] - sum[r - l + 2] - sum[n - 1] + sum[n - l + 1] + mod + mod)) % mod; 69 // [1, L ~ N - 1] 70 intersect = (intersect + sum[n - 1] - sum[l - 1] + mod) % mod; 71 // [2 ~ R, N] 72 intersect = (intersect + sum[n - 1] - sum[n - r] + mod) % mod; 73 // [L ~ M, M ~ R] 74 nonleaf = (nonleaf + r - l + 2 * (sum[2] + mod - sum[r - l + 2])) % mod; 75 } 76 LL ans = (intersect + leaf + mod - nonleaf) % mod; 77 printf("%lld\n", ans); 78 } 79 return 0; 80 }
1010 Swaps and Inversions
沙雕逆序对
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int maxn = 1e5 + 10; 5 int a[maxn]; 6 7 // BIT 8 int c[maxn]; 9 int lowbit(int s) { 10 return s & (-s); 11 } 12 void modify(int i, int x, int n) { 13 while (i <= n) c[i] += x, i += lowbit(i); 14 return; 15 } 16 int query(int i) { 17 int ret = 0; 18 while (i > 0) ret += c[i], i -= lowbit(i); 19 return ret; 20 } 21 22 vector<int> b; 23 int main() { 24 int n, x, y; 25 while(~scanf("%d %d %d", &n, &x, &y)) { 26 b.clear(); 27 for(int i = 1; i <= n; ++i) scanf("%d", a + i), b.push_back(a[i]); 28 sort(b.begin(), b.end()); 29 unique(unique(b.begin(), b.end()), b.end()); 30 for(int i = 1; i <= n; ++i) a[i] = lower_bound(b.begin(), b.end(), a[i]) - b.begin() + 1; 31 for(int i = 1; i <= n; ++i) c[i] = 0; 32 LL ans = 0; 33 for(int i = 1; i <= n; ++i) { 34 ans += query(n) - query(a[i]); 35 modify(a[i], 1, n); 36 } 37 printf("%lld\n", min(x, y) * ans); 38 } 39 return 0; 40 }