The 2021 China Collegiate Programming Contest (Harbin) J B I D

news/2024/10/21 7:48:15/

Dashboard - The 2021 China Collegiate Programming Contest (Harbin) - Codeforces

J

给一个n * m的矩阵,求该矩阵中有少个数既是改行最小,也是该列最小的。

数据范围是1000,可以先预处理行、列最小值,之后挨个判断是不是行最小且列最小的。

预处理:O(1e6),挨个判断:O(1e6),时间上够。

void solve() {int n,m; cin>>n>>m;vector<vector<int>> a(n, vector<int>(m));vector<int> row(n, INF), col(m, INF);for(int i = 0; i < n; ++i) {for(int j = 0; j < m; ++j) {cin>>a[i][j];row[i] = min(row[i], a[i][j]);col[j] = min(col[j], a[i][j]);}}int cnt = 0;for(int i = 0; i < n; ++i) {for(int j = 0; j < m; ++j) {cnt += (a[i][j] == row[i] && a[i][j] == col[j]);}}cout<<cnt<<endl;
}

B

给长度为n(1e5)的数组A,1 <= Ai <= 100,让找最长的一个序列满足:
A b 1 + A b 2 = A b 3 + A b 4 = . . . = A b m − 1 + A b m A_{b_1} + A_{b_2} = A_{b_3} + A_{b_4} = ... = A_{b_{m-1}} + A_{b_m} Ab1+Ab2=Ab3+Ab4=...=Abm1+Abm

1 ≤ b 1 < b 2 < b 3 < . . . < b m ≤ n 1 \le b_1 \lt b_2 \lt b_3 \lt ... \lt b_m \le n 1b1<b2<b3<...<bmn
观察Ai每个值都是1到100的,很小。且Ai + Aj的值是在2到200之间的。

同时,b是递增的。

我们可以考虑从前往后找值,使到t值时,前面有sum - t存在,那么计数加2,就这样从2到200进行枚举即可。如果是存在一个交叉的区间是满足相加是sum的,那么只能贡献2个,剩下的就不行。

例如:1 2 4 3 1 4。sum = 5是最多的:4。如果选1 4,那么那个2,就没有贡献,如果选2 3,那么那个1 4就没有贡献。交叉的最多贡献2个。

因此,从2到200枚举sum,暴力找满足条件的,贡献加2并清空数组继续。找每个sum中最大的贡献就是答案。

void solve() {int n; cin>>n;vector<int> a(n);for(auto &t: a) cin>>t;int ma = 0;array<int, 221> mp;mp.fill(0);for(int i = 2; i <= 200; ++i) {int cnt = 0;mp.fill(0);for(auto &t: a) {if(t >= i) continue;if(mp[i - t]) cnt += 2, mp.fill(0);else mp[t]++; }ma = max(ma, cnt);}cout<<ma<<endl;
}

I

长度为n的数组A,可以用任意次操作,求最少操作次使A全为0。操作是,选m个元素下标,B1 B2 ... Bm,让Abi减少·1 << i。一个元素可以在一次操作中出现不止一次。

发现,这个操作只对二进制下1的个数有关。我们不去考虑每个元素怎么操作,怎么分。我们考虑这个数组的所有元素二进制下1的位置的个数怎么变化。

第一个样例

5
1 2 3 4 5

在二进制下的表示

001 010 011 100 101

总的二进制位置数量

2 1 0
2 2 3

按从小到大

0 1 2
3 2 2

因为操作中一个元素可以出现任意次,所以用两次操作,可以让3 2 2转为1 0 0,之后再用一次操作转为全0。

同理,剩下俩样例都是这样。

n最多1e5,表示有一位最多是1e5个。如果在第一个非0和最后一个非0的位置中间存在有0,那么高位就要向低位填充,即高位减一,低位加2,经过一直这样操作,就存在一个从最低位开始只有一个连续的非0段。那么可以用操作来消去。这样一直循环判断,时间赋值度O(1e5 * 30),可以过。

void solve() {int n; cin>>n;vector<int> a(34);for(int i = 0; i < n; ++i) {int t; cin>>t;auto calc = [&](int x) -> void {int p = 0;while(x) {a[p++] += (x % 2);x /= 2;}};calc(t);}int ans = 0, r = 0;// 找高位非0位置auto find_r = [&]() -> void {r = 0;for(int i = 0; i <= 30; ++i) {if(a[i] == 0) continue;r = i;}};// 从低位到非0高位减去这段最小的auto sub = [&]() -> void {int mi = INF;for(int i = 0; i <= r; ++i) {mi = min(mi, a[i]);}ans += mi;for(int i = 0; i <= r; ++i) {a[i] -= mi;}};// 先找高位r,减去,再找高位rfind_r();sub();find_r();while(true) {// 用高位填充低位0int p = -1;for(int i = 0; i <= r; ++i) {if(a[i] == 0 && p == -1) {p = i;continue;}if(a[i] != 0 && p != -1) {a[p] = 2;for(int j = p + 1; j < i; ++j) a[j] = 1;a[i]--;if(a[i] == 0) p = i;else p = -1;}}if(p != -1) r = max(0, p-1);sub();find_r();// 如果高位就是0,表示只能全a[0]次操作if(r == 0) {ans += a[0];break;}}cout<<ans<<endl;
}

D

两个数,不超过LL范围,让两个数分区去掉相同的数,还使这俩数的相除得到的分数是相同的。输出最简的经操作过的俩数。

俩数最多18位,搜索会爆,但是1 << 18不会爆,大概是1e6,那就是状压,枚举子集。先枚举分子可以的情况,之后在枚举分母可能的情况,判断是否做分分数相同。

不过这题比较恶心的是,在输出时忽略前导零,但是在删除时,还要加上前导零。因为每次都是这俩数减去一个共同的数,在删除时要考虑前导零。

因此需要加上一个map进行映射,将删除的数字用字符串进行拼接,排序,和删除后得到的数放入同一个pair中。对分母/分子继续枚举子集,根据:
a b = x y \frac{a} b = \frac x y ba=yx
得到分子/分母,判断分母/分子删除的数拼接的字符串在和得到的分子/分母是否在map中存在,存在找分子最小的即可。

注意会爆LL,需要int128,不过只需要在做乘除时用int128,其他时候不用。

void solve() {int a,b; cin>>a>>b;string sa = to_string(a), sb = to_string(b);int alen = sa.length(), blen = sb.length();map<pair<string,int>, int> mp, mp2;for(int i = 0; i <= (1 << alen); ++i) {string del = "";int now = 0;for(int j = 0; j < alen; ++j) {if( (i >> j) & 1) {del += sa[j];} else now = now * 10 + (sa[j] - '0');}sort(all(del));mp[{del, now}] = 1;}int tp = LONG_LONG_MAX, btm;for(int i = 0; i <= (1 << blen); ++i) {string del = "";int now = 0;for(int j = 0; j < blen; ++j) {if( (i >> j) & 1) {del += sb[j];} else now = now * 10 + sb[j] - '0';}sort(all(del));if(!now) continue;if((__int128_t) a * now % (__int128_t)b) continue;int p = (__int128_t)a * now / b;if(mp.find({del, p}) != mp.end()) {if(p < tp) {tp = p;btm = now;}}}cout<<tp<<" "<<btm<<'\n';
}

不过我vp时,枚举子集枚举的是分子,之后找分母,找有无符合的分母。最后再判断前导0和位数什么的,结果wa9。不知道哪里错了,对拍没对出来(要改动数字的数据随机很难产生阿

2021CCPC 哈尔滨(B D E I J)_.Ashy.的博客-CSDN博客


http://www.ppmy.cn/news/1192833.html

相关文章

在NISQ小型计算机上执行大型并行量子计算的可能性

简介 Steve White提出了密度矩阵重整化群&#xff08;DMRG&#xff09;的基本思想&#xff0c;即纠缠是一种有价值的资源&#xff0c;可以用来精确或近似地描述大量子系统。后来&#xff0c;这一思想被理解为优化矩阵积状态&#xff08;MPS&#xff09;的算法&#xff0c;支持…

免费(daoban)gpt,同时去除广告

一. 内容简介 免费(daoban)gpt&#xff0c;同时去除广告&#xff0c;https://chat18.aichatos.xyz/&#xff0c;也可当gpt用&#xff0c;就是有点广告&#xff0c;大家也可以支持一下 二. 软件环境 2.1 Tampermonkey 三.主要流程 3.1 创建javascript脚本 点击添加新脚本 …

三维地图数据共享与统一存储

这家总部位于北京的高新企业是一家致力于三维数字地理技术的领军企业&#xff0c;提供中国领先的三维数据获取服务&#xff0c;并依据三维数据自动建模云计算服务、提供全国性的地图与位置服务。这项技术其实我们每天都有可能用到&#xff0c;例如百度地图、高德地图就属于三维…

一次cs上线服务器的练习

环境&#xff1a;利用vm搭建的环境 仅主机为65段 测试是否能与win10ping通 配置转发 配置好iis Kali访问测试 现在就用burp抓取winser的包 开启代理 使用默认的8080抓取成功 上线

【risc-v】 on fpga

https://github.com/T-head-Semi/openc906 https://github.com/T-head-Semi/openc906 https://stnolting.github.io/neorv32/#_general_purpose_input_and_output_port_gpio–neo xuantie linux risc-v

七月论文审稿GPT第二版:从Meta Nougat、GPT4审稿到mistral、llama longlora

前言 如此前这篇文章《学术论文GPT的源码解读与微调&#xff1a;从chatpaper、gpt_academic到七月论文审稿GPT》中的第三部分所述&#xff0c;对于论文的摘要/总结、对话、翻译、语法检查而言&#xff0c;市面上的学术论文GPT的效果虽暂未有多好&#xff0c;可至少还过得去&am…

执行java -jar后显示没有主清单属性

问题现象 执行java -jar后显示没有主清单属性 问题分析 缺少了项目maven插件 spring-boot-maven-plugin。 解决方法 查看项目打包的pom.xml文件中&#xff0c;添加配置如下&#xff1a; <!-- 打包格式 --><packaging>jar</packaging><!-- 打包插件 -…

【JAVA学习笔记】58 - 泛型

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter15/src/com/yinhai/generic_ https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter15/src/com/yinhai/customgeneric_ 一、泛型的入门和好处 1)请编写程序&#xff0c;…