\(\mathrm{sum}=100+100+100+20\)ide
今天題質量降低了。優化
另外精度偏差真的煩。code
因爲是排列,因此峯值必爲 \(n\),其它數能夠依次倒序選擇在 \(n\) 左邊或右邊,因此答案爲 \(2^{n-1}\)。blog
const int N = 0; const ll mod = 1e9 + 7; inline ll Read() { ll x = 0, f = 1; char c = getchar(); while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') f = -f, c = getchar(); while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar(); return x * f; } ll qpow(ll a, ll b) { ll ans = 1ll; for (; b; b >>= 1, a = a * a % mod) if (b & 1) ans = ans * a % mod; return ans; } int main() { printf ("%lld\n", qpow(2, Read() - 1)); return 0; }
已知一棵 \(n\) 個節點的有根樹。有 \(m\) 個詢問。每一個詢問給出了一對節點的編號 \(x\) 和 \(y\),詢問 \(x\) 與 \(y\) 的祖孫關係。排序
這不是 LCA 板題嗎。get
const int N = 4e4 + 10; inline ll Read() { ll x = 0, f = 1; char c = getchar(); while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') f = -f, c = getchar(); while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar(); return x * f; } int m, root, n, logN; struct edge { int to, nxt; }e[N << 1]; int head[N], tot; void add(int u, int v) { e[++tot] = (edge) {v, head[u]}, head[u] = tot; } bool vis[N]; int dep[N], f[N][30]; queue <int> q; void bfs(int root) { while(!q.empty()) q.pop(); q.push(root); vis[root] = 1; dep[root] = 1; while (!q.empty()) { int u = q.front(); q.pop(); for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (vis[v]) continue; vis[v] = 1; dep[v] = dep[u] + 1; f[v][0] = u; for (int j = 1; j <= logN; j++) f[v][j] = f[f[v][j-1]][j - 1]; q.push(v); } } } int LCA(int u, int v) { if (dep[u] > dep[v]) u ^= v ^= u ^= v; for (int j = logN; ~j; j--) if (dep[f[v][j]] >= dep[u]) v = f[v][j]; if (u == v) return u; for (int j = logN; ~j; j--) if (f[u][j] != f[v][j]) u = f[u][j], v = f[v][j]; u = f[u][0]; return u; } int main() { n = Read(); logN = 20; for (int i = 1; i <= n; i++) { int u = Read(), v = Read(); if (v == -1) root = u; else add (u, v), add (v, u); } bfs(root); for (m = Read(); m--; ) { int u = Read(), v = Read(); int lca = LCA(u, v); if (lca == u) puts("1"); else if (lca == v) puts("2"); else puts("0"); } return 0; }
\(A\) 隊和 \(B\) 隊的每一個人和其它隊隊員等機率匹配在一塊兒,比較權值,大者爲隊內貢獻 \((a_i-b_j)^2\) 分。求兩隊分數指望差。it
這裏等機率是 \(\frac{1}{n}\) 而不是 \(\frac{1}{n!}\),差點損失 \(100\mathrm{pts}\)。class
而後枚舉 \(B\) 隊在 \(A\) 中匹配,考慮暴力:queue
for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) if (a[i] > b[j]) sum += (a[i] - b[j]) * (a[i] - b[j]); else sum -= (a[i] - b[j]) * (a[i] - b[j]);
sum
即爲 \(A,B\) 隊權值差。im
考慮優化它,能夠先對 \(A\) 隊按權值升序排序,而後二分查找第最後一個小於 \(b\) 的位置 \(\mathrm{pos}\),即 \([1,\mathrm{pos}]\) 爲 \(A\) 隊貢獻,\([\mathrm{pos} + 1, n]\) 反之。
展開 \((x-y)^2=x^2+2xy+y^2\),代入題目:
再維護 \(a_i\) 的前綴和與 \({a_i}^2\) 的前綴和便可。
當心精度偏差,多用 long double
。
const int N = 50010; inline ll Read() { ll x = 0, f = 1; char c = getchar(); while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') f = -f, c = getchar(); while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar(); return x * f; } ll n; ll sum1[N], sum2[N]; double sum; ll a[N]; int main() { n = Read(); for (int i = 1; i <= n; i++) a[i] = Read(); sort (a + 1, a + 1 + n); for (int i = 1; i <= n; i++) sum1[i] = sum1[i - 1] + a[i], sum2[i] = sum2[i - 1] + a[i] * a[i]; for (int i = 1; i <= n; i++) { ll x = Read(); if (x <= a[1]) {sum += n * x * x + sum2[n] - 2ll * x * sum1[n]; continue;} if (x >= a[n]) {sum -= n * x * x + sum2[n] - 2ll * x * sum1[n]; continue;} ll pos = lower_bound(a + 1, a + 1 + n, x) - a - 1; sum += -(pos * x * x + sum2[pos] - 2ll * x * sum1[pos]) + (n - pos) * x * x + (sum2[n] - sum2[pos]) - 2ll * x * (sum1[n] - sum1[pos]); } // for (int i = 1; i <= n; i++) brute♂force // for (int j = 1; j <= n; j++) // if (a[i] > b[j]) sum += (a[i] - b[j]) * (a[i] - b[j]); // else sum -= (a[i] - b[j]) * (a[i] - b[j]); printf ("%lf", sum * 1.0 / n); return 0; }
找到一些數知足:
已知n,求合法的數的個數,答案很大,對 \(999983\) 取模忍一下。
考慮簡單容斥思想,即求出前 \(n\) 位之和與後 \(n\) 位之和相等的方案數 + 奇數位之和與偶數位之和相等的方案數 - 前 \(n\) 位之和與後 \(n\) 位之和相等且奇數位之和與偶數位之和相等的方案數。
設 \(f_{i,j}\) 表示前 \(i\) 位和爲 \(j\) 的方案數。
能夠把奇偶和相等的看做是前 \(n\) 位後 \(n\) 位和相等(即奇數位看做前 \(n\) 位,偶數位看做後 \(n\) 位)。而且能夠不用計算到 \(2n\) 這麼冗長,平方便可。那麼前 \(n\) 位之和與後 \(n\) 位之和相等的方案數 + 奇數位之和與偶數位之和相等的方案數就是:
前 \(n\) 位之和與後 \(n\) 位之和相等、奇數位之和與偶數位之和相等的方案數是有交集的,因此計算很麻煩,考慮轉化題意:
由於前 \(n\) 位之和等於後\(n\)位之和、奇數位之和等於偶數位之和,因此前 \(n\) 位中奇數位之和等於後n位中偶數位之和且前 \(n\) 位中偶數位之和等於後 \(n\) 位中奇數位之和。
這樣就無交集了。
const int N = 1010, M = 9010, mod = 999983; inline ll Read() { ll x = 0, f = 1; char c = getchar(); while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') f = -f, c = getchar(); while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar(); return x * f; } int n, m, K; char s[15]; int a[N]; int f[N][M]; bool num[15]; int main() { n = Read(); f[0][0] = 1; scanf ("%s", s + 1); m = strlen (s + 1); for (int i = 1; i <= m; i++) K = max(K, s[i] - '0'), f[1][s[i] - '0'] = 1, num[s[i] - '0'] = 1; for (int i = 2; i <= n; i++) for (int j = 0; j <= n * K; j++) for (int k = 0; k < 10; k++) if (num[k]) (f[i][j] += f[i - 1][j - k]) %= mod; int ans = 0; for (int i = 0; i <= n * K; i++) (ans += 2ll * f[n][i] * f[n][i] % mod) %= mod; int Even = n >> 1, Odd = n - Even, A = 0, B = 0; for (int i = 0; i <= Odd * K; i++) (A += 1ll * f[Odd][i] * f[Odd][i] % mod) %= mod; for (int i = 0; i <= Even * K; i++) (B += 1ll * f[Even][i] * f[Even][i] % mod) %= mod; printf ("%d", (ans - 1ll * A * B % mod + mod) % mod); return 0; }