比赛链接 / 官方题解链接
A. Berland Poker Solution 如果 jokers 数量小于等于手牌数量,就把所有 jokers 揽入自己手中;否则,剩余的 jokers 平摊给其他人。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <bits/stdc++.h> using namespace std;template <typename T>void read (T&x) {x=0 ;int fl=1 ;char ch=getchar ();while (ch<'0' ||ch>'9' ){if (ch=='-' )fl=-1 ;ch=getchar ();}while (ch>='0' &&ch<='9' ){x=(x<<1 )+(x<<3 )+ch-'0' ;ch=getchar ();}x*=fl;} template <typename T,typename ...Args>inline void read (T&t,Args&...args) {read (t);read (args...);}typedef long long LL;typedef vector<int > vi;typedef pair<int , int > pii;#define mp(x, y) make_pair(x, y) #define pb(x) emplace_back(x) int T, n, m, k;int main () { for (read (T); T; T--){ read (n, m, k); if (m <= n / k) printf ("%d\n" , m); else { m -= n / k; int d = m / (k - 1 ); if (m % (k - 1 )) d++; printf ("%d\n" , n / k - d); } } return 0 ; }
B. New Theatre Square Solution 对每一行单独计算,令 y=\min\{y, 2x\} ,然后优先放 1\times2 的瓷砖。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <bits/stdc++.h> using namespace std;template <typename T>void read (T&x) {x=0 ;int fl=1 ;char ch=getchar ();while (ch<'0' ||ch>'9' ){if (ch=='-' )fl=-1 ;ch=getchar ();}while (ch>='0' &&ch<='9' ){x=(x<<1 )+(x<<3 )+ch-'0' ;ch=getchar ();}x*=fl;} template <typename T,typename ...Args>inline void read (T&t,Args&...args) {read (t);read (args...);}typedef long long LL;typedef vector<int > vi;typedef pair<int , int > pii;#define mp(x, y) make_pair(x, y) #define pb(x) emplace_back(x) int T, x, y, n, m;char s[1005 ];int main () { for (read (T); T; T--){ read (n, m, x, y); if (y > 2 * x) y = 2 * x; LL ans = 0 ; for (int i = 1 ; i <= n; i++){ scanf ("%s" , s+1 ); for (int j = 1 ; j <= m; j++){ if (s[j] == '.' ){ if (j < m && s[j+1 ] == '.' ){ ans += y; j++; } else ans += x; } } } printf ("%lld\n" , ans); } return 0 ; }
C. Mixing Water Solution 温度变化为:h,\frac{h+c}{2},\frac{2h+c}{3},\frac{h+c}{2},\frac{3h+2c}{5},\frac{h+c}{2},\cdots 偶数项均为 \frac{h+c}{2} ,奇数(第 2k-1 )项为 \frac{kh+(k-1)c}{2k-1} .
由于所有温度均大于等于 \frac{h+c}{2} ,所以如果 t\leq\frac{h+c}{2} ,那么答案就是 2 ;否则,我们在奇数项中寻找最接近答案的一项。
设第 k 项温度正好是 t ,那么 \frac{kh+(k-1)c}{2k-1}=t ,化简得:k=\frac{t-c}{2t-h-c} . 由于实际上不会正好等于,我们比较一下 k-1,k,k+1 就好。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <bits/stdc++.h> using namespace std;template <typename T>void read (T&x) {x=0 ;int fl=1 ;char ch=getchar ();while (ch<'0' ||ch>'9' ){if (ch=='-' )fl=-1 ;ch=getchar ();}while (ch>='0' &&ch<='9' ){x=(x<<1 )+(x<<3 )+ch-'0' ;ch=getchar ();}x*=fl;} template <typename T,typename ...Args>inline void read (T&t,Args&...args) {read (t);read (args...);}typedef long long LL;typedef vector<int > vi;typedef pair<int , int > pii;#define mp(x, y) make_pair(x, y) #define pb(x) emplace_back(x) int T;LL c, h, t; inline double tem (LL k) { return (double )(k * h + (k-1 ) * c) / (2 *k-1 ); } int main () { for (read (T); T; T--){ read (h, c, t); if (t <= 0.5 * (h + c)){ puts ("2" ); continue ; } LL k = (t - c) / (2 * t - h - c); LL ans = 2 ; double mn = t - 0.5 * (h + c); if (fabs (tem (k) - t) < mn){ mn = fabs (tem (k) - t); ans = 2 * k - 1 ; } k--; if (fabs (tem (k) - t) < mn){ mn = fabs (tem (k) - t); ans = 2 * k - 1 ; } k += 2 ; if (fabs (tem (k) - t) < mn){ mn = fabs (tem (k) - t); ans = 2 * k - 1 ; } printf ("%lld\n" , ans); } return 0 ; }
D. Yet Another Yet Another Task Solution 注意到 -30\leq a_i\leq30 范围很小,所以枚举最大值 mx ,然后 dp 寻找最大子段和,且子段中最大值不大于 mx .
设 dp[i] 表示以 a[i] 结尾的最大子段和(a[i] 必选),并且要满足这个子段中最大值不大于 mx ;设 st[i] 表示这个最大子段和的起始位置,那么容易有 dp 方程:dp[i]=\begin{cases}-INF,&a[i]>mx\\dp[i-1]+a[i],&a[i]\leq mx\and dp[i-1]\geq0\\a[i],&a[i]\leq mx\and dp[i-1]<0\end{cases} ,对应有 st[i]=\begin{cases}无,&a[i]>mx\\st[i-1],&a[i]\leq mx\and dp[i-1]\geq0\\i,&a[i]\leq mx\and dp[i-1]<0\end{cases} . 如果 [i,st[i]] 中包含了 mx ,就用 dp[i]-mx 去更新答案。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <bits/stdc++.h> using namespace std;template <typename T>void read (T&x) {x=0 ;int fl=1 ;char ch=getchar ();while (ch<'0' ||ch>'9' ){if (ch=='-' )fl=-1 ;ch=getchar ();}while (ch>='0' &&ch<='9' ){x=(x<<1 )+(x<<3 )+ch-'0' ;ch=getchar ();}x*=fl;} template <typename T,typename ...Args>inline void read (T&t,Args&...args) {read (t);read (args...);}typedef long long LL;typedef vector<int > vi;typedef pair<int , int > pii;#define mp(x, y) make_pair(x, y) #define pb(x) emplace_back(x) const int N = 100005 ;int n, a[N], cnt[N][100 ], ans = -1e9 ;int main () { read (n); for (int i = 1 ; i <= n; i++){ read (a[i]); for (int j = -30 ; j <= 30 ; j++) cnt[i][j+30 ] = cnt[i-1 ][j+30 ]; cnt[i][a[i]+30 ]++; } for (int mx = -30 ; mx <= 30 ; mx++){ vi dp (n+5 , -1e9 ) , st (n+5 , 0 ) ; for (int i = 1 ; i <= n; i++){ if (a[i] > mx) continue ; if (dp[i-1 ] < 0 ){ dp[i] = a[i]; st[i] = i; } else { dp[i] = a[i] + dp[i-1 ]; st[i] = st[i-1 ]; } } for (int i = 1 ; i <= n; i++){ if (dp[i] == -1e9 ) continue ; if (cnt[i][mx+30 ] - cnt[st[i]-1 ][mx+30 ] > 0 ) ans = max (ans, dp[i] - mx); } } printf ("%d\n" , ans); return 0 ; }
E. Modular Stability Solution 假设我们选取 x=a_k ,那么取第一个模数为 a_k ,可以知道答案应为 0 ;此时,若取第一个模数为 a_1 ,那么有:a_k\bmod a_1=0 ,也即 a_k 是 a_1 倍数;同理我们可以证明:a_2,a_3,\cdots,a_k 均是 a_1 的倍数。
至于有没有其他条件约束,我在比赛时没有去证明了(因为可以从样例中得到验证)。
所以我们枚举 a_1 的取值,得到 [1,n] 中 a_1 的倍数的个数,设为 m ,那么从这 m-1 个数(剔除 a_1 本身)选取 k-1 个数作为 a_2,a_3,\cdots,a_k 即可,所以共有 C_{m-1}^{k-1} 中选法。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 #include <bits/stdc++.h> using namespace std;template <typename T>void read (T&x) {x=0 ;int fl=1 ;char ch=getchar ();while (ch<'0' ||ch>'9' ){if (ch=='-' )fl=-1 ;ch=getchar ();}while (ch>='0' &&ch<='9' ){x=(x<<1 )+(x<<3 )+ch-'0' ;ch=getchar ();}x*=fl;} template <typename T,typename ...Args>inline void read (T&t,Args&...args) {read (t);read (args...);}typedef long long LL;typedef vector<int > vi;typedef pair<int , int > pii;#define mp(x, y) make_pair(x, y) #define pb(x) emplace_back(x) const LL MOD = 998244353 ;const int N = 500005 ;LL n, k, ans, fact[N], invfact[N]; inline LL fpow (LL bs, LL idx) { LL res = 1 ; bs %= MOD; while (idx){ if (idx & 1 ) (res *= bs) %= MOD; (bs *= bs) %= MOD; idx >>= 1 ; } return res; } inline LL C (LL m, LL r) { return fact[m] * invfact[r] % MOD * invfact[m-r] % MOD; } int main () { fact[0 ] = 1 , invfact[0 ] = 1 ; for (int i = 1 ; i <= 500000 ; i++){ fact[i] = i * fact[i-1 ] % MOD; invfact[i] = fpow (fact[i], MOD - 2 ); } read (n, k); if (n < k) return puts ("0" ); for (LL i = 1 ; i <= n; i++){ LL cnt = n / i; if (cnt < k) break ; (ans += C (cnt - 1 , k - 1 )) %= MOD; } printf ("%lld\n" , ans); return 0 ; }