2022 China Collegiate Programming Contest (CCPC) Guangzhou Onsite

向右看齐 2024-02-05 11:56 162阅读 0赞

L. Station of Fate

741f41074eef4fe9a518714d73a01463.png

求组合数,考虑先分配再排列

  1. #include <bits/stdc++.h>
  2. #define int long long
  3. using i64 = long long;
  4. constexpr int N = 1e6 + 10;
  5. constexpr int M = 1e6 + 10;
  6. constexpr int P = 2600;
  7. constexpr i64 Inf = 1e18;
  8. constexpr int mod = 998244353;
  9. constexpr double eps = 1e-6;
  10. int n, k;
  11. int Fac[N], inv[N];
  12. int qpow(int a, int b) {
  13. int res = 1;
  14. while(b) {
  15. if (b & 1) res = (res * a) % mod;
  16. a = (a * a) % mod;
  17. b >>= 1;
  18. }
  19. return res;
  20. }
  21. void F_init() {
  22. Fac[0] = 1;
  23. for (int i = 1; i < N; i ++) {
  24. Fac[i] = (Fac[i - 1] * i) % mod;
  25. }
  26. inv[N - 1] = qpow(Fac[N - 1], mod - 2);
  27. for (int i = N - 2; i >= 0; i --) {
  28. inv[i] = (inv[i + 1] * (i + 1)) % mod;
  29. }
  30. }
  31. int C(int n, int m) {
  32. return Fac[n] * inv[m] % mod * inv[n - m] % mod;
  33. }
  34. void solve() {
  35. std::cin >> n >> k;
  36. std::cout << C(n - 1, k - 1) * Fac[n] % mod << "\n";
  37. }
  38. signed main() {
  39. std::ios::sync_with_stdio(false);
  40. std::cin.tie(nullptr);
  41. int t = 1;
  42. std::cin >> t;
  43. F_init();
  44. while (t--) {
  45. solve();
  46. }
  47. return 0;
  48. }

E. Elevator

1cb4b01b4a87411e959f3d6f6c9cf158.png

思路

首先第一个难点是怎么把应用场景变得具象化,你会发现题面写的有点抽象

其实可以考虑一排电梯,速度从快到慢排列,那么在某一时刻,高度是递减的

那么操作实际就是阻碍一个电梯,然后其他所有电梯往上移动一格

等效于所有电梯不动,一个电梯往下移动一格

然后问题就是

对于第 i 个电梯,让它变成高度最大的,编号最小的操作次数最少是多少

我们发现对于相邻的询问,我们可以考虑变化量(DS思想)

第 i 个比第 i - 1 个多了哪部分呢

容易发现我们只需要对比自己高度大的操作,把所有左边高度比自己高的削成和自己一样高,然后再加上左边有多少编号比自己小的

这两部分的贡献,第一部分可以直接算,第二部分用 BIT 维护即可

  1. #include <bits/stdc++.h>
  2. #define lowbit(x) ((x) & (-x))
  3. #define int long long
  4. #define endl '\n'
  5. using namespace std;
  6. const int N = 1e6 + 10, MOD = 998244353;
  7. struct node {
  8. int x, id;
  9. const bool operator< (const node &b) const { return x < b.x || (x == b.x && id < b.id); }
  10. }a[N];
  11. int ans[N], sum[N];
  12. namespace Fenwick{
  13. int a[N], len;
  14. void add(int x, int v) {
  15. for(; x <= len; x += lowbit(x)) a[x] += v;
  16. }
  17. int query(int x, int ans = 0) {
  18. for(; x >= 1; x -= lowbit(x)) ans += a[x];
  19. return ans;
  20. }
  21. }
  22. inline void solve() {
  23. int n, m; cin >> n >> m;
  24. Fenwick::len = n;
  25. for(int i = 1; i <= n; i++) cin >> a[i].x, a[i].id = i;
  26. sort(a + 1, a + 1 + n);
  27. for(int i = 2; i <= n; i++) {
  28. sum[a[i].id] = sum[a[i - 1].id] + (i - 1) * (a[i].x - a[i - 1].x);
  29. }
  30. for(int i = 1; i <= n; i++) {
  31. sum[a[i].id] += Fenwick::query(a[i].id);
  32. Fenwick::add(a[i].id, 1);
  33. }
  34. for(int i = 1; i <= n; i++) {
  35. if(sum[i] > m - 2) cout << -1 << endl;
  36. else cout << sum[i] << endl;
  37. }
  38. }
  39. signed main() {
  40. ios_base::sync_with_stdio(false), cin.tie(0);
  41. int t = 1; // cin >> t;
  42. while(t--) solve();
  43. return 0;
  44. }

H. GameX

821c496526ef4299b5244a45fd9e90d6.png

思路

首先结论就是A操作的数一定是未出现过的最小奇数,B操作的数一定是未出现的最小偶数

然后就直接模拟即可

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. #define rep(i,a,n) for(int i=a; i<=n ;i++)
  4. #define pb push_back
  5. using namespace std;
  6. const int mxn = 2e5+7, mxm = 1e6;
  7. int a[mxn];
  8. void work(){
  9. int n, k;
  10. cin >> n >> k;
  11. int tk=k;
  12. map<int,int> vis;
  13. rep(i,1,n) cin >> a[i], vis[a[i]]++;
  14. sort(a+1,a+n+1);
  15. //rep(i,1,n) cout << a[i] <<" \n"[i==n];
  16. int A=0, B=0, bi=0;
  17. while(1){
  18. if(!k) break;
  19. if(vis[bi]) {bi+=2; continue;}
  20. vis[bi]=1;
  21. bi+=2;
  22. k--;
  23. }
  24. int ai=1;
  25. while(1){
  26. if(!tk) break;
  27. if(vis[ai]) {ai+=2;continue;}
  28. vis[ai]=1;
  29. ai+=2;
  30. tk--;
  31. }
  32. int ansi = -1;
  33. int i=0;
  34. while(1){
  35. if(vis[i]) {i++;continue;}
  36. ansi=i;
  37. break;
  38. i++;
  39. }
  40. // cout << ansi <<'\n';
  41. if(ansi%2==0) cout <<"Alice"<<'\n';
  42. else cout <<"Bob"<<'\n';
  43. }
  44. signed main(){
  45. ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
  46. int T=1;
  47. cin >> T;
  48. while(T--){
  49. work();
  50. }
  51. return 0;
  52. }

I. Infection

a7f00ff9db954d46ad9a54c38b1cc4d6.png

711bab140b6c4ee2abd48e9630e39b26.png

f93eeb9342c041db9ec627ce37e61993.png

  1. #include <bits/stdc++.h>
  2. #define int long long
  3. constexpr int N = 2e3 + 10;
  4. constexpr int mod = 1e9 + 7;
  5. std::vector<int> adj[N];
  6. int n;
  7. int sum = 0;
  8. int a[N];
  9. int sz[N], Fa[N];
  10. int p[N], inv[N];
  11. int ans[N];
  12. int f[N][N], g[N][N];
  13. int qpow(int a, int b) {
  14. int res = 1;
  15. while(b) {
  16. if (b & 1) res = (res * a) % mod;
  17. a = (a * a) % mod;
  18. b >>= 1;
  19. }
  20. return res;
  21. }
  22. void dfs(int u, int fa) {
  23. sz[u] = 1;
  24. Fa[u] = fa;
  25. static int tmp1[N], tmp2[N];
  26. f[u][1] = p[u];
  27. g[u][1] = a[u] * qpow(sum, mod - 2) % mod;
  28. f[u][0] = ((1 - p[u]) % mod + mod) % mod;
  29. g[u][0] = ((1 - p[u]) % mod + mod) % mod;
  30. for (auto v : adj[u]) {
  31. if (v == fa) continue;
  32. dfs(v, u);
  33. for (int k = 0; k <= sz[u] + sz[v]; k ++) tmp1[k] = tmp2[k] = 0;
  34. for (int k = 1; k <= sz[u]; k ++) {
  35. for (int l = 0; l <= sz[v]; l ++) {
  36. tmp1[k + l] += f[u][k] * f[v][l] % mod;
  37. tmp2[k + l] += g[u][k] * f[v][l] % mod;
  38. if (l) tmp2[k + l] += f[u][k] * g[v][l] % mod;
  39. tmp1[k + l] %= mod;
  40. tmp2[k + l] %= mod;
  41. }
  42. }
  43. for (int k = 1; k <= sz[u] + sz[v]; k ++) {
  44. f[u][k] = tmp1[k];
  45. g[u][k] = tmp2[k];
  46. }
  47. sz[u] += sz[v];
  48. }
  49. }
  50. void solve() {
  51. std::cin >> n;
  52. for (int i = 1; i <= n - 1; i ++) {
  53. int u, v;
  54. std::cin >> u >> v;
  55. adj[u].push_back(v);
  56. adj[v].push_back(u);
  57. }
  58. for (int i = 1; i <= n; i ++) {
  59. int b, c;
  60. std::cin >> a[i] >> b >> c;
  61. sum += a[i];
  62. sum %= mod;
  63. p[i] = b * qpow(c, mod - 2) % mod;
  64. }
  65. dfs(1, 0);
  66. for (int i = 1; i <= n; i ++) {
  67. for (int j = 1; j <= n; j ++) {
  68. if (j == 1) ans[i] += g[j][i];
  69. else ans[i] += g[j][i] * (1 - p[Fa[j]] + mod) % mod;
  70. ans[i] %= mod;
  71. }
  72. }
  73. for (int i = 1; i <= n; i ++) {
  74. std::cout << ans[i] % mod << "\n";
  75. }
  76. }
  77. signed main() {
  78. std::ios::sync_with_stdio(false);
  79. std::cin.tie(nullptr);
  80. int t = 1;
  81. while(t --) {
  82. solve();
  83. }
  84. return 0;
  85. }

发表评论

表情:
评论列表 (有 0 条评论,162人围观)

还没有评论,来说两句吧...

相关阅读