A. Goals of Victory 大致题意 有 $n$ 只队伍,所有队伍两两对战,两个队伍因此得分之和一定为 0。将每个队伍的所有得分之和相加,现在已知其中 $n-1$ 个队伍的得分情况,问最后一个队伍的得分情况是
思路 简单题,说白了就是所有人分数之和肯定是 $0$,那就把剩下的人都加起来,取负数就行了
AC code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void solve () { int _; cin >> _; for (int ts = 0 ; ts < _; ++ts) { int n; cin >> n; int tot = 0 ; for (int i = 0 ; i < n - 1 ; ++i) { int tmp; cin >> tmp; tot += tmp; } cout << -tot << endl; } }
B. Helmets in Night Light 大致题意 村长需要通知村里的所有人一个消息,村长每通知一个人,就要花费 $k$ 的成本,而听到消息的村民也可以相互通知,每个村民最多再通知 $a_i$ 个其他村民,同时每通知一个其他村民就要花费 $b_i$ 的费用,问最少的费用
思路 村长可以无限通知,但是成本固定,所以能让成本低的村民通知的情况下,村长只需要通知一次即可,当成本低的村民的通知机会都用完了之后,剩下的都村长通知一下就行了
AC 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 #define int long long void solve () { int _; cin >> _; for (int ts = 0 ; ts < _; ++ts) { int n, p; cin >> n >> p; vector<pair<int , int >> data (n); for (auto &i: data) cin >> i.second; for (auto &i: data) cin >> i.first; int cost = p, cnt = 1 ; sort (data.begin (), data.end ()); for (auto &i: data) { if (i.first >= p) break ; int c = min (n - cnt, i.second); cnt += c; cost += c * i.first; if (cnt == n) break ; } cost += p * (n - cnt); cout << cost << endl; } }
C. Joyboard 大致题意 有一个数组 $a$,其长度为 $n+1$,现在需要往第 $n+1$ 这个位置上放上一个在 $[0, m]$ 的整数,然后对于每一个 $a_i = a_{i+1} % i$ 问,如果希望整个数组中恰好有 $k$ 种不同的数字,则 $n+1$ 这个位置上的选择有多少
思路 首先,无论最终填上的值有多大,最终只要经过第一层 $mod$ 操作后,其值一定在 $[0, n)$ 之间了,且经历第二次 $mod$ 操作后,一定会变成 $0$(因为计算是从大到小进行计算的,所以一定会遇到相同的值,否则都是大于当前值的,不会改变 $mod$ 的结果)。所以最终一定最多只能存在 $3$ 个不同的数字。
那么什么时候为 $1$ 个呢,也很简单,因为最终一定为 $0$,故开始值也必须为 $0$
然后是两个的情况,那么如果我一开始的值就是在 $[0, n)$ 之内,那么必然也可以满足,因为遇到的第一个可以 $mod$ 的值就是它自己
但是要考虑一种特殊情况,那就是恰好是 ${n, 2 \times n, 3 \times n \dots}$ 的情况,因为虽然不在 $[0, n)$ 之内,但是第一次 $mod$ 会直接变成 $0$
AC code 1 2 3 4 5 6 7 8 9 10 11 12 void solve () { int _; cin >> _; for (int ts = 0 ; ts < _; ++ts) { int n, m, k; cin >> n >> m >> k; if (k == 1 ) cout << 1 << endl; else if (k == 2 ) cout << min (m, n) + (m > n ? (m / n) - 1 : 0 ) << endl; else if (k == 3 ) cout << max (0 , m - n) - (m > n ? (m / n) - 1 : 0 ) << endl; else cout << 0 << endl; } }
D. Effects of Anti Pimples 大致题意 有一个数组 $a$,开始的时候都是白色,每次可以任意选择一个或者几个数字,将其染上黑色。然后将每个黑色的位置下标的倍数处,染成绿色。最后从不是白色的块中选出值最高的。问所有的选择情况下,所有得到的值之和是多少
思路 看起来很简单,但是实际上也非常简单的题
如果一个值被染成黑色,那么其能够带来的效果是确定的,即其倍数上的节点中最大的那个,我们将其先成为可能最大值
接下来是统计每个最大值的出现的次数,简单来说就是相同的可能最大值中挑选任意几个(至少一个),然后在剩下的可能最大值小于当前值中挑选 $0$ 个或者多个即可,即 $\sum{i=1}^{t} \binom{i}{t} * \sum {i=0}^{n-t} \binom{i}{n-t}$
而这里的求和又非常的简单,因为 $\sum_{i=0}^{x} \binom{i}{x} = 2^x$,所以,就非常简单了
AC 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 #define int long long void solve () { const int mod = 998244353 ; vector<int > c0 (1e5 +10 ) , c1 (1e5 +10 ) ; c0[0 ] = 1 ; c1[0 ] = 0 ; for (int i = 1 ; i < c0.size (); ++i) { c0[i] = (c0[i - 1 ] * 2 ) % mod; c1[i] = (c0[i] + mod - 1 ) % mod; } int n; cin >> n; vector<int > data (n) , top (n) ; for (auto &i: data) cin >> i; for (int i = 0 ; i < n; ++i) { top[i] = data[i]; for (int j = i + 1 ; j <= n; j += i + 1 ) top[i] = max (top[i], data[j - 1 ]); } map<int , int > cnt; for (auto &i: top) cnt[i]++; int last = n, ans = 0 ; for (auto iter = cnt.rbegin (); iter != cnt.rend (); ++iter) { last -= iter->second; ans = (ans + ((iter->first * ((c1[iter->second] * c0[last]) % mod)) % mod)) % mod; } cout << ans << endl; }