A:ios
發現最優的方案必定是選 $ l $ 和 $ 2 * l $,題目保證有解,直接輸出便可c++
#include <bits/stdc++.h> #define Fast_cin ios::sync_with_stdio(false), cin.tie(); #define rep(i, a, b) for(register int i = a; i <= b; i++) #define per(i, a, b) for(register int i = a; i >= b; i--) #define DEBUG(x) cerr << "DEBUG" << x << " >>> " << endl; using namespace std; typedef unsigned long long ull; typedef long long ll; template <typename _T> inline void read(_T &f) { f = 0; _T fu = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') fu = -1; c = getchar(); } while(c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = getchar(); } f *= fu; } template <typename T> void print(T x) { if(x < 0) putchar('-'), x = -x; if(x < 10) putchar(x + 48); else print(x / 10), putchar(x % 10 + 48); } template <typename T> void print(T x, char t) { print(x); putchar(t); } int T, l, r; int main() { read(T); while(T--) { read(l); read(r); print(l, ' '); print(2 * l, '\n'); } return 0; }
B:數組
狀況 1:全部字母都相同,輸出 $ n * (n - 1) / 2 $ 便可
狀況 2:左邊有連續 $ x $ 個字母相同,右邊有 $ y $ 個,第一個字母和最後一個字符相同,輸出 $ (x + 1) * (y + 1) $
狀況 3:左邊有連續 $ x $ 個字母相同,右邊有 $ y $ 個,第一個字母和最後一個字符不一樣,輸出 $ x + y + 2 - 1 $,最後的 $ -1 $ 是由於整個串被算了 $ 2 $ 次函數
#include <bits/stdc++.h> #define Fast_cin ios::sync_with_stdio(false), cin.tie(); #define rep(i, a, b) for(register int i = a; i <= b; i++) #define per(i, a, b) for(register int i = a; i >= b; i--) #define DEBUG(x) cerr << "DEBUG" << x << " >>> " << endl; using namespace std; typedef unsigned long long ull; typedef long long ll; template <typename _T> inline void read(_T &f) { f = 0; _T fu = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') fu = -1; c = getchar(); } while(c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = getchar(); } f *= fu; } template <typename T> void print(T x) { if(x < 0) putchar('-'), x = -x; if(x < 10) putchar(x + 48); else print(x / 10), putchar(x % 10 + 48); } template <typename T> void print(T x, char t) { print(x); putchar(t); } const int N = 2e5 + 5, md = 998244353; char c[N]; int cnt[23333]; int n, cut1 = -1, cut2 = -1; inline int mul(int x, int y) { return (ll)x * y % md; } int main() { read(n); scanf("%s", c + 1); for(register int i = 2; i <= n; i++) if(c[i] != c[i - 1]) { cut1 = i - 1; break; } for(register int i = n - 1; i >= 1; i--) if(c[i] != c[i + 1]) { cut2 = i + 1; break; } if(cut1 == -1) cout << (ll)n * (n - 1) / 2 % md << endl; else if(c[1] == c[n]) cout << mul(cut1 + 1, n - cut2 + 2) << endl; else cout << cut1 + 1 + n - cut2 + 2 - 1 << endl; return 0; }
C:oop
答案本質上是把一個圓切成答案份ui
那麼圓心角肯定了,就能夠算出一個圓周角的大小,若是切成 360 份能夠拼出任意角度,因此枚舉這個角度便可spa
#include <bits/stdc++.h> #define Fast_cin ios::sync_with_stdio(false), cin.tie(); #define rep(i, a, b) for(register int i = a; i <= b; i++) #define per(i, a, b) for(register int i = a; i >= b; i--) #define DEBUG(x) cerr << "DEBUG" << x << " >>> " << endl; using namespace std; typedef unsigned long long ull; typedef long long ll; template <typename _T> inline void read(_T &f) { f = 0; _T fu = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') fu = -1; c = getchar(); } while(c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = getchar(); } f *= fu; } template <typename T> void print(T x) { if(x < 0) putchar('-'), x = -x; if(x < 10) putchar(x + 48); else print(x / 10), putchar(x % 10 + 48); } template <typename T> void print(T x, char t) { print(x); putchar(t); } int T; int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } int main() { read(T); while(T--) { int d; read(d); int ans = -1; for(register int i = 3; i <= 23333; i++) { if(d * i % 180 == 0 && d <= 180 - 360 / (double)i) { ans = i; break; } } print(ans, '\n'); } return 0; }
D:code
$ f[i][j] $ 表示到了第 $ i $ 個字母,$ hard $ 已經匹配到了第 $ j $ 個字母的最小代價ci
直接 $ dp $ 便可get
#include <bits/stdc++.h> #define int long long #define Fast_cin ios::sync_with_stdio(false), cin.tie(); #define rep(i, a, b) for(register int i = a; i <= b; i++) #define per(i, a, b) for(register int i = a; i >= b; i--) #define DEBUG(x) cerr << "DEBUG" << x << " >>> " << endl; using namespace std; typedef unsigned long long ull; typedef long long ll; template <typename _T> inline void read(_T &f) { f = 0; _T fu = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') fu = -1; c = getchar(); } while(c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = getchar(); } f *= fu; } template <typename T> void print(T x) { if(x < 0) putchar('-'), x = -x; if(x < 10) putchar(x + 48); else print(x / 10), putchar(x % 10 + 48); } template <typename T> void print(T x, char t) { print(x); putchar(t); } const int N = 1e5 + 5; int f[N][5], w[N]; char c[N]; int n; int calc(char t) { if(t == 'h') return 1; if(t == 'a') return 2; if(t == 'r') return 3; if(t == 'd') return 4; return 0; } #undef int int main() { #define int long long memset(f, -1, sizeof(f)); read(n); scanf("%s", c + 1); for(register int i = 1; i <= n; i++) read(w[i]); f[0][0] = 0; for(register int i = 0; i < n; i++) { int val = calc(c[i + 1]); for(register int j = 0; j <= 3; j++) { if(f[i][j] == -1) continue; if(val == j + 1) { if(f[i + 1][j + 1] == -1) f[i + 1][j + 1] = f[i][j]; else f[i + 1][j + 1] = min(f[i + 1][j + 1], f[i][j]); if(f[i + 1][j] == -1) f[i + 1][j] = f[i][j] + w[i + 1]; else f[i + 1][j] = min(f[i + 1][j], f[i][j] + w[i + 1]); } else { if(f[i + 1][j] == -1) f[i + 1][j] = f[i][j]; else f[i + 1][j] = min(f[i + 1][j], f[i][j]); } } } int ans = f[n][0]; for(register int i = 0; i <= 3; i++) if(f[n][i] != -1) ans = min(ans, f[n][i]); cout << ans << endl; return 0; }
E:
沒寫出來,先咕了
update:2019.1.2
去年不會這題,今年來補
$ n $ 爲人數,總分爲 $ s $,本身的下限 $ r $ , $ c $ 爲組合數,枚舉有多少我的跟本身得分相同,本身的得分 $ j $,對答案的貢獻是 $ C[n - 1][i - 1] * \frac{1}{i} * calc(n - i, s - i * j, j) $
$ calc( n, s, big ) $ 表示有 $ n $ 我的,總分爲 $ s $,每一個人的得分都 $ < big $ 的方案數,這個能夠經過容斥求出
總方案數能夠用隔板法求出是 $ C[s - r + n - 1][n - 1] $,乘上這個的逆元便可
#include <bits/stdc++.h> #define CIOS ios::sync_with_stdio(false); #define rep(i, a, b) for(register int i = a; i <= b; i++) #define per(i, a, b) for(register int i = a; i >= b; i--) #define DEBUG(x) cerr << "DEBUG" << x << " >>> "; using namespace std; typedef unsigned long long ull; typedef long long ll; template <typename T> inline void read(T &f) { f = 0; T fu = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') fu = -1; c = getchar(); } while (c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = getchar(); } f *= fu; } template <typename T> void print(T x) { if (x < 0) putchar('-'), x = -x; if (x < 10) putchar(x + 48); else print(x / 10), putchar(x % 10 + 48); } template <typename T> void print(T x, char t) { print(x); putchar(t); } const int N = 5005, md = 998244353; inline int mul(int x, int y) { return (ll)x * y % md; } inline int add(int x, int y) { x += y; if(x >= md) x -= md; return x; } inline int sub(int x, int y) { x -= y; if(x < 0) x += md; return x; } inline int fpow(int x, int y) { int ans = 1; while(y) { if(y & 1) ans = mul(ans, x); y >>= 1; x = mul(x, x); } return ans; } int C[N + 105][105], inv[N]; int n, s, r, ans; int calc(int n, int s, int big) { if(n == 0) return s == 0; int ans = 0; for(register int i = 0, opt = 1; i <= n && i * big <= s; i++, opt = md - opt) ans = add(ans, mul(opt, mul(C[s - i * big + n - 1][n - 1], C[n][i]))); return ans; } int main() { read(n); read(s); read(r); for(register int i = 0; i <= s + n; i++) { C[i][0] = 1; for(register int j = 1; j <= i && j <= n; j++) C[i][j] = add(C[i - 1][j - 1], C[i - 1][j]); } for(register int i = 1; i <= n; i++) inv[i] = fpow(i, md - 2); for(register int i = 1; i <= n; i++) { for(register int j = r; j <= s; j++) { if(s - i * j < 0) break; ans = add(ans, mul(mul(C[n - 1][i - 1], calc(n - i, s - i * j, j)), inv[i])); } } print(mul(ans, fpow(C[s - r + n - 1][n - 1], md - 2)), '\n'); return 0; } // Rotate Flower Round.
F:
分別計算 $ -1 $ 和 $ -1 $ 的貢獻,$ -1 $ 和數字的貢獻,數字和數字的貢獻
第一個用 $ dp $ 求出,第二個用前綴和求出,第三個用樹狀數組求出
$ sb $ 的我能用前綴和的地方寫了樹狀數組
#include <bits/stdc++.h> #define Fast_cin ios::sync_with_stdio(false), cin.tie(); #define rep(i, a, b) for(register int i = a; i <= b; i++) #define per(i, a, b) for(register int i = a; i >= b; i--) #define DEBUG(x) cerr << "DEBUG" << x << " >>> " << endl; using namespace std; typedef unsigned long long ull; typedef long long ll; template <typename _T> inline void read(_T &f) { f = 0; _T fu = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') fu = -1; c = getchar(); } while(c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = getchar(); } f *= fu; } template <typename T> void print(T x) { if(x < 0) putchar('-'), x = -x; if(x < 10) putchar(x + 48); else print(x / 10), putchar(x % 10 + 48); } template <typename T> void print(T x, char t) { print(x); putchar(t); } const int N = 2e5 + 5, md = 998244353; inline int mul(int x, int y) { return (ll)x * y % md; } inline int add(int x, int y) { x += y; if(x >= md) x -= md; return x; } inline int sqr(int x) { return mul(x, x); } inline int fpow(int x, int y) { int ans = 1; while(y) { if(y & 1) ans = mul(ans, x); y >>= 1; x = sqr(x); } return ans; } int a[N], s[N], f[N], fac[N]; int n, inv2 = (md + 1) / 2, ans1; inline int lowbit(int x) { return x & -x; } void change(int x, int y) { for(register int i = x; i <= n; i += lowbit(i)) f[i] += y; } int query(int x) { int ans = 0; for(register int i = x; i; i -= lowbit(i)) ans += f[i]; return ans; } int main() { read(n); fac[0] = 1; for(register int i = 1; i <= n; i++) read(a[i]), fac[i] = mul(fac[i - 1], i), s[i] = 1; for(register int i = n; i >= 1; i--) { if(a[i] == -1) continue; ans1 = add(ans1, query(a[i])); change(a[i], 1); } memset(f, 0, sizeof(f)); for(register int i = 1; i <= n; i++) { if(a[i] != -1) s[a[i]] = 0; } for(register int i = 1; i <= n; i++) s[i] += s[i - 1]; ans1 = mul(ans1, fac[s[n]]); for(register int i = 1; i <= s[n]; i++) f[i] = add(f[i - 1], mul(mul(fac[s[n]], fpow(i, md - 2)), mul(i - 1, mul(i, inv2)))); ans1 = add(ans1, f[s[n]]); memset(f, 0, sizeof(f)); for(register int i = 1; i <= n; i++) if(a[i] == -1) change(i, 1); for(register int i = 1; i <= n; i++) { if(a[i] == -1) continue; int val = mul(s[a[i]], query(n) - query(i)); val = add(val, mul(s[n] - s[a[i]], query(i))); val = mul(val, fac[s[n] - 1]); ans1 = add(ans1, val); } print(mul(ans1, fpow(fac[s[n]], md - 2)), '\n'); return 0; }
G:
看到揹包問題就會想到卷積,由於揹包的轉移和卷積的形式相同
對於最開始的 $ k $ 個數構造生成函數,計算 $ n / 2 $ 次冪,每一位的平方加起來就是答案啦
#pragma GCC target("avx") #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize("unroll-loops") #pragma GCC optimize("Ofast") #include <bits/stdc++.h> #define Fast_cin ios::sync_with_stdio(false), cin.tie(); #define rep(i, a, b) for(register int i = a; i <= b; i++) #define per(i, a, b) for(register int i = a; i >= b; i--) #define DEBUG(x) cerr << "DEBUG" << x << " >>> " << endl; using namespace std; typedef unsigned long long ull; typedef long long ll; template <typename _T> inline void read(_T &f) { f = 0; _T fu = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') fu = -1; c = getchar(); } while(c >= '0' && c <= '9') { f = (f << 3) + (f << 1) + (c & 15); c = getchar(); } f *= fu; } template <typename T> void print(T x) { if(x < 0) putchar('-'), x = -x; if(x < 10) putchar(x + 48); else print(x / 10), putchar(x % 10 + 48); } template <typename T> void print(T x, char t) { print(x); putchar(t); } const int P = 998244353; inline int add(int x, int y) { x += y; if(x >= P) x -= P; return x; } inline int sub(int x, int y) { x -= y; if(x < 0) x += P; return x; } inline int mul(int x, int y) { return (ll)x * y % P; } inline int fpow(int x, int y) { int ans = 1; while(y) { if(y & 1) ans = mul(ans, x); y >>= 1; x = mul(x, x); } return ans; } namespace ntt { int base = 1, root = -1, maxbase = -1; vector <int> roots = {0, 1}, rev = {0, 1}; void init() { int tmp = P - 1; maxbase = 0; while(!(tmp & 1)) { tmp >>= 1; maxbase++; } root = 2; while(1) { if(fpow(root, 1 << maxbase) == 1 && fpow(root, 1 << (maxbase - 1)) != 1) break; root++; } } void ensure_base(int nbase) { if(maxbase == -1) init(); if(nbase <= base) return; assert(nbase <= maxbase); rev.resize(1 << nbase); for(register int i = 1; i < (1 << nbase); i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (nbase - 1)); roots.resize(1 << nbase); while(base < nbase) { int z = fpow(root, 1 << (maxbase - base - 1)); for(register int i = (1 << (base - 1)); i < (1 << base); i++) { roots[i << 1] = roots[i]; roots[i << 1 | 1] = mul(roots[i], z); } base++; } } void dft(vector <int> &a) { int n = a.size(), zeros = __builtin_ctz(n); ensure_base(zeros); int shift = base - zeros; for(register int i = 0; i < n; i++) if(i < (rev[i] >> shift)) swap(a[i], a[rev[i] >> shift]); for(register int mid = 1; mid < n; mid <<= 1) { for(register int i = 0; i < n; i += (mid << 1)) { for(register int j = 0; j < mid; j++) { int x = a[i + j], y = mul(a[i + j + mid], roots[mid + j]); a[i + j] = add(x, y); a[i + j + mid] = sub(x, y); } } } } vector <int> pmul(vector <int> a, vector <int> b, bool is_sqr = false) { int need = a.size() + b.size() - 1, nbase = 0; while((1 << nbase) < need) nbase++; ensure_base(nbase); int size = 1 << nbase; a.resize(size); dft(a); if(!is_sqr) b.resize(size), dft(b); else b = a; int inv = fpow(size, P - 2); for(register int i = 0; i < size; i++) a[i] = mul(a[i], mul(b[i], inv)); reverse(a.begin() + 1, a.end()); dft(a); a.resize(need); return a; } vector <int> psqr(vector <int> a) { return pmul(a, a, 1); } vector <int> inv(vector <int> a, int size) { if(size == 1) return vector <int> { fpow(a[0], P - 2) }; vector <int> b = inv(a, size >> 1); a = pmul(a, psqr(b)); b.resize(size); for(register int i = 0; i < size; i++) b[i] = sub(add(b[i], b[i]), a[i]); return b; } vector <int> pinv(vector <int> a) { int nbase = 0; while((1 << nbase) < a.size()) nbase++; return inv(a, 1 << nbase); } } using ntt::pmul; using ntt::psqr; vector <int> wxw, ans; int n, k, sum; int main() { read(n); read(k); wxw.resize(10); for(register int i = 1; i <= k; i++) { int t; read(t); wxw[t] = 1; } n >>= 1; ans = wxw; n--; while(n) { if(n & 1) ans = pmul(ans, wxw); n >>= 1; wxw = psqr(wxw); } for(register int i = 0; i < ans.size(); i++) sum = add(sum, mul(ans[i], ans[i])); cout << sum << endl; return 0; }