The 2021 ICPC Asia Regionals Online Contest (II)【解题报告】

2024-03-30 13:38

本文主要是介绍The 2021 ICPC Asia Regionals Online Contest (II)【解题报告】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我进入比赛


Problem A. Sort

题目大意

T T T 组,每组给出一个长度为 n n n 的序列 a [ ] a[] a[] 和 整数 k k k.

定义一次操作为将序列 a [ ] a[] a[] 分割成 v i v_i vi 段,再对段做置换 p i p_i pi.

若在有限次数操作中,无法使得序列 a [ ] a[] a[] 变成非降序,则输出 − 2 -2 2.

若在有限次数操作中,可以使得序列 a [ ] a[] a[] 变成非降序,且 ∑ v i ≤ 3 n \sum{v_i} \leq 3n vi3n,则输出方案,否则输出 − 1 -1 1.

1 ≤ T ≤ 1 0 3 , 1 ≤ k , n ≤ 1 0 3 , 1 ≤ a [ i ] ≤ 1 0 9 , ∑ n ≤ 3 × 1 0 4 1 \leq T \leq 10^3, 1 \leq k,n \leq 10^3,1 \leq a[i] \leq 10^9, \sum{n} \leq 3\times 10^4 1T103,1k,n103,1a[i]109,n3×104.

分析

不难发现,当 k ≥ 3 k \geq 3 k3 时,总可以构造出合法方案,就是一傻逼模拟题(被细节搞炸

k = 2 k=2 k=2 时,注意这个样例

2
3 2
1 2 1
2 1 2

代码实现

#include <bits/stdc++.h>
using namespace std;const int M = (int)1e3;int n, k;
int a[M + 5];
int b[M + 5];bool is_sort(int p)
{for(int i = 1; i < n; ++i){if(a[(i + p - 2) % n + 1] > a[(i + p - 1) % n + 1]) return 0;}return 1;
}void work()
{scanf("%d %d", &n, &k);for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);if(n == 1) printf("0\n");else if(k == 1){if(is_sort(1)) printf("0\n");else           printf("-2\n");}else if(k == 2){if(is_sort(1)) printf("0\n");else{for(int i = 1; i <= n; ++i){if(is_sort(i)){printf("1\n");printf("2\n");printf("%d %d %d\n", 0, i - 1, n);printf("2 1\n");for(int j = 1; j <= n; ++j) b[j] = a[j];for(int j = 1; j <= n - i + 1; ++j) a[j] = b[j - 1 + i];for(int j = n - i + 2; j <= n; ++j) a[j] = b[j - n + i - 1];return;}}printf("-2\n");}}else if(k >= 3){printf("%d\n", n - 1);for(int i = 1; i < n; ++i){int p = i; for(int j = i; j <= n; ++j) if(a[p] > a[j]) p = j;if(i == p){printf("2\n");printf("%d %d %d\n", 0, 1, n);printf("1 2\n");}else if(i == 1){printf("2\n");printf("%d %d %d\n", 0, p - 1, n);printf("2 1\n");for(int j = 1; j <= n; ++j) b[j] = a[j];for(int j = 1; j <= n - p + 1; ++j) a[j] = b[j + p - 1];for(int j = n - p + 2; j <= n; ++j) a[j] = b[j - n + p - 1];}else{printf("3\n");printf("%d %d %d %d\n", 0, i - 1, p - 1, n);printf("1 3 2\n");for(int j = 1; j <= n; ++j) b[j] = a[j];for(int j = 1; j <= i - 1; ++j) a[j] = b[j];for(int j = i; j <= i + n - p; ++j) a[j] = b[j - i + p];for(int j = i + n - p + 1; j <= n; ++j) a[j] = b[j - n + p - 1];}}}
}int main()
{int T; scanf("%d", &T);for(int ca = 1; ca <= T; ++ca){work();}return 0;
}

Problem G. Limit

题目大意

给出 n , a i , b i , t n, a_i, b_i, t n,ai,bi,t,求 lim ⁡ x → 0 ∑ i = 1 n a i l n ( 1 + b i x ) x t \lim\limits_{x \rightarrow 0}{\frac{\sum_{i=1}^n{a_i ln(1+b_ix)}}{x^t}} x0limxti=1nailn(1+bix).

1 ≤ n ≤ 1 0 5 , − 100 ≤ a , b ≤ 100 , 0 ≤ t ≤ 5 1 \leq n \leq 10^5, -100 \leq a, b \leq 100, 0 \leq t \leq 5 1n105,100a,b100,0t5.

分析

神他喵抓大头,直接无脑泰勒展开(赛时还想多项式卷积

结论:三个人都不会高数

代码实现

#include <bits/stdc++.h>
using namespace std;typedef long long ll;int n, t;
ll c[10];void work()
{scanf("%d %d", &n, &t);for(int i = 1, a, b; i <= n; ++i){scanf("%d %d", &a, &b);ll cur = a;for(int j = 1; j <= t; ++j){cur *= b;c[j] += ((j&1) ? cur : -cur);}}if(!t) printf("0\n");else{for(int i = 1; i < t; ++i){if(c[i]){printf("infinity\n");return;}}if(c[t] == 0) printf("0\n");else{ll d = (ll)abs(__gcd(1ll * t, c[t]));ll up = c[t] / d, dn = t / d;if(dn == 1) printf("%lld\n", up);else       printf("%lld/%d\n", up, dn);}}
}int main()
{work();return 0;
}

Problem H. Set

题目大意

定义集合 S = { 1 , 2 , ⋯ , 256 } S=\{1,2, \cdots, 256\} S={1,2,,256},给出两个整数 k k k r r r.

要求构造集合 S S S k k k 个子集 I i I_i Ii,要求对任意的 1 ≤ i 1 < i 2 < ⋯ < i r ≤ n 1 \leq i_1 < i_2 < \cdots < i_r \leq n 1i1<i2<<irn 满足 ∣ ⋃ j = 1 r I i j ∣ ≥ 128 |\bigcup_{j=1}^{r}{I_{i_j}}| \geq 128 j=1rIij128,且 m a x { ∣ I i ∣ } ≤ ⌈ 512 r ⌉ max\{|I_i|\} \leq \lceil \frac{512}{r} \rceil max{Ii}r512.

3 ≤ r ≤ k ≤ 26 3 \leq r \leq k \leq 26 3rk26.

分析

直接 rand 所有子集就行了…

证明以后再补(咕咕咕

代码实现

#include <bits/stdc++.h>
using namespace std;int Rand(int l, int r)
{return rand() % (r - l + 1) + l;
}void work()
{int k, r; scanf("%d %d", &k, &r);for(int i = 1; i <= k; ++i){set<int> st;while((int)st.size() < (512 + r - 1) / r) st.insert(Rand(1, 256));for(int j = 1; j <= 256; ++j){printf("%d", st.count(j));}printf("\n");}
}int main()
{srand(time(NULL));work();return 0;
}

Problem J. Leaking Roof

题目大意

给一个 n × n n \times n n×n 的矩阵 h i j h_{ij} hij 表示 ( i , j ) (i,j) (i,j) 的高度.

现在每个单元都下了 m m m 单位的雨水, ( i , j ) (i,j) (i,j) 的雨水会平均地流向四周高度比它低的单元.

若高度为 0 0 0 的点有雨水,则这个点会漏水.

求足够长时间后,每个点的漏水量.

1 ≤ n ≤ 500 , 0 ≤ m , h i j ≤ 1 0 4 1 \leq n \leq 500, 0 \leq m,h_{ij} \leq 10^4 1n500,0m,hij104.

分析

按照高度依次处理雨水的流动,模拟就行了.

代码实现

#include <bits/stdc++.h>
using namespace std;const int M = (int)5e2;int n, m;
int h[M + 5][M + 5];
int id[M * M + 5];
double a[M + 5][M + 5];
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};bool cmp(int a, int b)
{return h[a / n][a % n] > h[b / n][b % n];
}void work()
{scanf("%d %d", &n, &m);for(int i = 0; i < n; ++i){for(int j = 0; j < n; ++j){id[i * n + j] = i * n + j;scanf("%d", &h[i][j]);a[i][j] = 1.0 * m;}}sort(id, id + n * n, cmp);for(int i = 0; i < n * n; ++i){int x = id[i] / n, y = id[i] % n, c = 0;for(int j = 0; j < 4; ++j){int xx = x + dx[j], yy = y + dy[j];if(xx >= 0 && xx < n && yy >= 0 && yy < n && h[xx][yy] < h[x][y]) ++c;}if(c){for(int j = 0; j < 4; ++j){int xx = x + dx[j], yy = y + dy[j];if(xx >= 0 && xx < n && yy >= 0 && yy < n && h[xx][yy] < h[x][y]) a[xx][yy] += a[x][y] / c;}a[x][y] = 0;}}for(int i = 0; i < n; ++i) for(int j = 0; j < n; ++j) printf("%.9f%c", h[i][j] ? 0 : a[i][j], j == n - 1 ? '\n' : ' ');
}int main()
{work();return 0;
}

Problem K. Meal

题目大意

n n n 个人, n n n 道菜,第 i i i 个人对第 j j j 道菜的好感度为 a i j a_{ij} aij.

初始,集合 S = { 1 , 2 , ⋯ , n } S = \{1,2,\cdots ,n\} S={1,2,,n}.

n n n 个人按照序号轮流点菜,对于第 i i i 个人,他点到第 j j j 道菜的概率为 a i j ∑ k ∈ S a i k \frac{a_{ij}}{\sum_{k \in S}{a_{ik}}} kSaikaij,然后把 j j j S S S 中删除.

求第 i i i 个人点到第 j j j 道菜的概率.

1 ≤ n ≤ 20 , 1 ≤ a i j ≤ 100 1 \leq n \leq 20, 1 \leq a_{ij} \leq 100 1n20,1aij100.

分析

状压DP模板题~

代码实现

#include <bits/stdc++.h>
using namespace std;typedef long long ll;const int M = (int)20;
const ll mod = (ll)998244353;int n, a[M][M];
int f[1<<M];
int s[1<<M];
int p[M][M];ll quick(ll a, ll b, ll p = mod)
{ll s = 1;while(b){if(b & 1) s = s * a % p;a = a * a % p;b >>= 1;}return s % p;
}ll inv(ll n, ll p = mod)
{return quick(n, p - 2, p);
}void work()
{scanf("%d", &n);for(int i = 0; i < n; ++i) for(int j = 0; j < n; ++j) scanf("%d", &a[i][j]);for(int i = 0; i < (1<<n); ++i){int c = __builtin_popcount(i);for(int j = 0; j < n; ++j) if(!(i>>j&1)) s[i] += a[c][j];s[i] = inv(s[i]);}f[0] = 1;for(int i = 1; i < (1<<n); ++i){int c = __builtin_popcount(i) - 1;for(int j = 0; j < n; ++j){if(!(i>>j&1)) continue;(p[c][j] += 1ll * f[i^(1<<j)] * a[c][j] % mod * s[i^(1<<j)] % mod) %= mod;(f[i] += 1ll * f[i^(1<<j)] * a[c][j] % mod * s[i^(1<<j)] % mod) %= mod;}}for(int i = 0; i < n; ++i) for(int j = 0; j < n; ++j) printf("%d%c", p[i][j], j == n - 1 ? '\n' : ' ');
}int main()
{work();return 0;
}

Problem L. Euler Function

题目大意

n n n 个数 a [ ] a[] a[] m m m 次操作.

操作分为两种

0 l r w 0 \; l \; r \; w 0lrw 表示 a [ i ] ∗ = w i ∈ [ l , r ] a[i] *= w \quad i \in [l, r] a[i]=wi[l,r].

1 l r 1 \; l \; r 1lr 表示查询 ∑ i = l r φ ( a [ i ] ) \sum_{i=l}^{r}{\varphi(a[i])} i=lrφ(a[i]).

1 ≤ n , m ≤ 1 0 5 , 1 ≤ a i , w ≤ 100 , 1 ≤ l ≤ r ≤ n 1 \leq n,m \leq 10^5, 1 \leq a_i,w \leq 100, 1 \leq l \leq r \leq n 1n,m105,1ai,w100,1lrn.

分析

势能线段树(之前见过,但这是第一次知道还有这个名字

改了改线段树的码风

代码实现

#include <bits/stdc++.h>
using namespace std;typedef long long ll;const int M = (int)1e5;
const int N = (int)1e2;
const ll mod = (ll)998244353;bool is_prime[N + 5];
int prime[N + 5], cnt;
int pw[N + 5][M + 5];void init()
{memset(is_prime, 1, sizeof(is_prime));cnt = is_prime[0] = is_prime[1] = 0;for(int i = 2; i <= N; ++i){if(is_prime[i]) prime[++cnt] = i;for(int j = 1; j <= cnt && i * prime[j] <= N; ++j){is_prime[i * prime[j]] = 0;if(i % prime[j] == 0) break;}}for(int i = 1; i <= cnt; ++i){pw[i][0] = 1; for(int j = 1; j <= M; ++j) pw[i][j] = 1ll * pw[i][j - 1] * prime[i] % mod;}
}int n, m;
struct tnode
{int s[M * 4 + 5], lz[M * 4 + 5][26]; bool is[M * 4 + 5][26];inline int lc(int k) {return k<<1;}inline int rc(int k) {return k<<1|1;}inline void push_up(int k){int l = lc(k), r = rc(k);s[k] = (s[l] + s[r]) % mod;for(int i = 1; i <= cnt; ++i) is[k][i] = (is[l][i]&is[r][i]);}inline void push_down(int k){int l = lc(k), r = rc(k);for(int i = 1; i <= cnt; ++i){if(!lz[k][i]) continue;s[l] = 1ll * s[l] * pw[i][lz[k][i]] % mod, lz[l][i] += lz[k][i];s[r] = 1ll * s[r] * pw[i][lz[k][i]] % mod, lz[r][i] += lz[k][i];lz[k][i] = 0;}}void build(int k, int l, int r){if(l == r){int x; scanf("%d", &x);s[k] = x;for(int i = 1; i <= cnt && prime[i] * prime[i] <= x; ++i){if(x % prime[i] == 0){s[k] = s[k] / prime[i] * (prime[i] - 1);is[k][i] = 1;while(x % prime[i] == 0) x /= prime[i];}}if(x > 1) s[k] = s[k] / x * (x - 1), is[k][lower_bound(prime + 1, prime + cnt + 1, x) - prime] = 1;return;}int mid = (l + r) >> 1;build(lc(k), l, mid);build(rc(k), mid + 1, r);push_up(k);}void update(int k, int l, int r, int a, int b, int p, int c){if(l >= a && r <= b && is[k][p]){s[k] = 1ll * s[k] * pw[p][c] % mod;lz[k][p] += c;return;}if(l == r){s[k] = 1ll * s[k] * (pw[p][c] - pw[p][c - 1]) % mod;is[k][p] = 1;return;}push_down(k);int mid = (l + r) >> 1;if(a <= mid) update(lc(k), l, mid, a, b, p, c);if(mid < b)  update(rc(k), mid + 1, r, a, b, p, c);push_up(k);}int query(int k, int l, int r, int a, int b){if(l >= a && r <= b) return s[k];push_down(k);int mid = (l + r) >> 1, sum = 0;if(a <= mid) (sum += query(lc(k), l, mid, a, b)) %= mod;if(mid < b)  (sum += query(rc(k), mid + 1, r, a, b)) %= mod;return sum;}
} tr;void work()
{scanf("%d %d", &n, &m);tr.build(1, 1, n);for(int i = 1, op, l, r, w; i <= m; ++i){scanf("%d", &op);if(op == 0){scanf("%d %d %d", &l, &r, &w);for(int j = 1; j <= cnt && prime[j] * prime[j] <= w; ++j){if(w % prime[j]) continue;int c = 0;while(w % prime[j] == 0) ++c, w /= prime[j];tr.update(1, 1, n, l, r, j, c);}if(w > 1) tr.update(1, 1, n, l, r, lower_bound(prime + 1, prime + cnt + 1, w) - prime, 1);}else{scanf("%d %d", &l, &r);printf("%d\n", (tr.query(1, 1, n, l, r) % mod + mod) % mod);}}
}int main()
{
//    freopen("input.txt", "r", stdin);init();work();return 0;
}

Problem M. Addition

题目大意

定义 n n n 2 2 2 进制数表示为 ∑ i = 0 n v a l i × 2 i × s g n [ i ] \sum_{i=0}^n{val_i \times 2^i \times sgn[i]} i=0nvali×2i×sgn[i].

给出 n , s g n [ ] n,sgn[] n,sgn[] v a l a i , v a l b i val_{a_i}, val_{b_i} valai,valbi,令 c = a + b c = a + b c=a+b,求出 c c c 的上述表示.

32 ≤ n ≤ 60 , s g n i ∈ { − 1 , 1 } , v a l a i ∈ { 0 , 1 } , v a l b i ∈ { 0 , 1 } 32 \leq n \leq 60, sgn_i \in \{-1, 1\}, val_{a_i} \in \{0,1\}, val_{b_i} \in \{0,1\} 32n60,sgni{1,1},valai{0,1},valbi{0,1}.

分析

连续的低位会构成连续的值域,因此只需要从高到低扫一遍,逐一确认每一位即可.

代码实现

#include <bits/stdc++.h>
using namespace std;typedef long long ll;const int M = (int)1e2;int n;
int sgn[M + 5];
ll mi[M + 5], mx[M + 5];
int ans[M + 5];void work()
{scanf("%d", &n);for(int i = 0; i < n; ++i) scanf("%d", &sgn[i]);if(sgn[0] == 1) mi[0] = 0, mx[0] = 1;else            mi[0] = -1, mx[0] = 0;for(int i = 1; i < n; ++i){if(sgn[i] == 1) mi[i] = mi[i - 1], mx[i] = mx[i - 1] + (1ll<<i);else            mi[i] = mi[i - 1] - (1ll<<i), mx[i] = mx[i - 1];}ll a = 0; for(int i = 0, x; i < n; ++i) scanf("%d", &x), a += (1ll<<i) * x * sgn[i];ll b = 0; for(int i = 0, x; i < n; ++i) scanf("%d", &x), b += (1ll<<i) * x * sgn[i];ll c = a + b;for(int i = n - 1; i >= 0; --i){if(i){if(mi[i - 1] <= c && c <= mx[i - 1]) ans[i] = 0;else    c -= sgn[i] * (1ll<<i), ans[i] = 1;}else if(c) ans[i] = 1;}for(int i = 0; i < n; ++i) printf("%d%c", ans[i], i == n - 1 ? '\n' : ' ');
}int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);work();return 0;
}

这篇关于The 2021 ICPC Asia Regionals Online Contest (II)【解题报告】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/861630

相关文章

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

2014 Multi-University Training Contest 8小记

1002 计算几何 最大的速度才可能拥有无限的面积。 最大的速度的点 求凸包, 凸包上的点( 注意不是端点 ) 才拥有无限的面积 注意 :  凸包上如果有重点则不满足。 另外最大的速度为0也不行的。 int cmp(double x){if(fabs(x) < 1e-8) return 0 ;if(x > 0) return 1 ;return -1 ;}struct poin

2014 Multi-University Training Contest 7小记

1003   数学 , 先暴力再解方程。 在b进制下是个2 , 3 位数的 大概是10000进制以上 。这部分解方程 2-10000 直接暴力 typedef long long LL ;LL n ;int ok(int b){LL m = n ;int c ;while(m){c = m % b ;if(c == 3 || c == 4 || c == 5 ||

2014 Multi-University Training Contest 6小记

1003  贪心 对于111...10....000 这样的序列,  a 为1的个数,b为0的个数,易得当 x= a / (a + b) 时 f最小。 讲串分成若干段  1..10..0   ,  1..10..0 ,  要满足x非递减 。  对于 xi > xi+1  这样的合并 即可。 const int maxn = 100008 ;struct Node{int

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

从0到1,AI我来了- (7)AI应用-ComfyUI-II(进阶)

上篇comfyUI 入门 ,了解了TA是个啥,这篇,我们通过ComfyUI 及其相关Lora 模型,生成一些更惊艳的图片。这篇主要了解这些内容:         1、哪里获取模型?         2、实践如何画一个美女?         3、附录:               1)相关SD(稳定扩散模型的组成部分)               2)模型放置目录(重要)

Regionals 2004 Asia - Beijing Argus 小根堆

点击打开链接 小根堆 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.util.StringTokeni

学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

文章目录 删除排序链表中的重复元素我的思路解法一:循环解法二:递归 网上思路 删除排序链表中的重复元素 II我的思路网上思路 总结 删除排序链表中的重复元素 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 图一 图二 示例 1:(图一)输入:head = [1,1,2]输出:[1,2]示例 2:(图

Python:豆瓣电影商业数据分析-爬取全数据【附带爬虫豆瓣,数据处理过程,数据分析,可视化,以及完整PPT报告】

**爬取豆瓣电影信息,分析近年电影行业的发展情况** 本文是完整的数据分析展现,代码有完整版,包含豆瓣电影爬取的具体方式【附带爬虫豆瓣,数据处理过程,数据分析,可视化,以及完整PPT报告】   最近MBA在学习《商业数据分析》,大实训作业给了数据要进行数据分析,所以先拿豆瓣电影练练手,网络上爬取豆瓣电影TOP250较多,但对于豆瓣电影全数据的爬取教程很少,所以我自己做一版。 目