2021“MINIEYE杯”中国大学生算法设计超级联赛(1)个人解题报告
文章目录
- HDU6950 Mod, Or and Everything
- HDU6954 Minimum spanning tree
- HDU6958 KD-Graph
- HDU6957 Maximal submatrix
- HDU6955 Xor sum
中超联赛
CSL中超可没巨佬们训练强度大
“什么是BSGS、莫队、KD tree”
我看我是完全不懂噢
HDU6950 Mod, Or and Everything
题意
求(nmod1)∣(nmod2)∣...∣(nmod(n−1))(n\ mod\ 1)|(n\ mod \ 2)|...|(n\ mod\ (n-1))(n mod 1)∣(n mod 2)∣...∣(n mod (n−1))的值
分析
打比赛时,
队友:经过化简可以得到答案为2k−12^k-12k−1
我:观察样例可以得到答案为2k−12^k-12k−1
QAQ
而实际上std的思路:nmodi≤⌈n2⌉−1n\ mod\ i \leq \lceil \frac{n}{2}\rceil-1n mod i≤⌈2n⌉−1,所以nmod(n−i)=in\ mod\ (n-i)=in mod (n−i)=i
所以这个和值就是000到⌈n2⌉−1\lceil \frac{n}{2}\rceil-1⌈2n⌉−1的所有整数的和. 求出来是2k−12^k-12k−1,这里的kkk是某个带nnn的式子,懒得认真推的话可以根据样例猜出,是令n=2xn=2^xn=2x,这个xxx向下取整再减1得到kkk. 但如果xxx本来就是整数,那么xxx还要再减去1.(总之看代码吧,或者去看std代码)
代码
#include <bits/stdc++.h>
#define fors(i, a, b) for(int i = (a); i <= (b); ++i)
#define lson k<<1
#define rson k<<1|1
#define pb push_back
#define lowbit(x) ((x)&(-(x)))
#define mem(a) memset(a, 0, sizeof(a))
#define DDLC_ESCAPE_PLAN_FAILED ios::sync_with_stdio(false), cin.tie(0)
#define int long long
const int inf = 0x3f3f3f3f;
const double dinf = 1e100;
typedef long long ll;
//const ll linf = 9223372036854775807LL;
// const ll linf = 1e18;
using namespace std;signed main()
{DDLC_ESCAPE_PLAN_FAILED;int t;cin >> t;while(t--){int n;cin >> n;int x = 0, res = n;while(res){res >>= 1LL;x++;}if(n == 1LL){cout << 0 << endl;continue; }if(n == (1LL << (x - 1LL))) x--;cout << (1LL << (x - 1LL)) - 1LL << endl;}return 0;
}
HDU6954 Minimum spanning tree
题意
有一个n−1n-1n−1个节点的带权完全图,节点标记为2,3,...,n2,3,...,n2,3,...,n. 完全图中从点iii到点jjj的边的权值大小为lcm(i,j)lcm(i,j)lcm(i,j),请你求出这个图的最小生成树。n≤10000000n\leq 10000000n≤10000000.
分析
容易知道,对任何一个边(i,j)(i,j)(i,j),这个边的权值不会小于max(i,j)max(i,j)max(i,j).
那么对于一个合数,它连向自己的因子即可,这时候边的权值就是这个合数。由于因子一定比自己小,所以在2,3,..i2,3,..i2,3,..i中一定存在。
而对于一个质数xxx,和任意一点iii相连,都有lcm(x,i)=x⋅ilcm(x,i)=x·ilcm(x,i)=x⋅i. 故令iii最小,取2即可保证边权最小。
分析完毕。找出质数,然后分类处理即可。线性筛处理之
其他
首先看到题:哇,1e81e81e8的范围,这怎么做。这算法都给限制到O(n)O(n)O(n)了,难不成是有什么公式?
思考一会之后:(其实已经得到正解)用线性筛试一波,自己调试1.5秒,完蛋
尝试各种卡常之后:优化到1.1秒了,实在顶不住了,要不直接交?
交上去之后:卧槽,MLE,那我不求MSTMSTMST前缀和了吧,直接算,但是这样更容易超时了,纠结
再交:居然700多ms过了,杭电评测机强啊
打完比赛后,才发现,原来数据规模看错了,是1e71e71e7,根本不需要卡()
代码
#include <bits/stdc++.h>
#define fors(i, a, b) for(int i = (a); i <= (b); ++i)
#define lson k<<1
#define rson k<<1|1
#define pb push_back
#define lowbit(x) ((x)&(-(x)))
#define mem(a) memset(a, 0, sizeof(a))
#define DDLC_ESCAPE_PLAN_FAILED ios::sync_with_stdio(false), cin.tie(0)
#define int long long
const int inf = 0x3f3f3f3f;
const double dinf = 1e100;
typedef long long ll;
//const ll linf = 9223372036854775807LL;
// const ll linf = 1e18;
using namespace std;
const int maxn = 1e7 + 10; // 比赛的时候看成1e8,导致多了一次MLE
bool p[maxn];
int pr[maxn];
int pre[maxn];
void Prime(){int cnt = 0;mem(p);p[0] = p[1] = 1;for(int i = 2; i < maxn; ++i){if(!p[i]) pr[cnt++] = i;for(int j = 0; j < cnt && pr[j] * i < maxn; ++j){p[pr[j] * i] = 1;if(i % pr[j] == 0) break;}}pre[0] = pre[1] = pre[2] = 0;for(int i = 3; i < maxn; ++i){if(!p[i]) pre[i] = pre[i - 1] + 2 * i;else pre[i] = pre[i - 1] + i;}
}
signed main()
{DDLC_ESCAPE_PLAN_FAILED;int t;cin >> t;Prime();while(t--){int n;cin >> n;cout << pre[n] << endl;}return 0;
}
HDU6958 KD-Graph
看到过题数不多以及题面比较奇怪就没做了,以后一定不能盲目看榜,以及耐心读懂题
题意
有一个nnn点mmm边的图(n≤100000n\leq100000n≤100000, m≤500000m\leq500000m≤500000),你需要将其分割成恰好KKK组,满足:
- 每组中任取两个点p,qp,qp,q,他们之间的路径中,最长边不大于DDD
- 不同组中任取两个点p,qp,qp,q,他们之间的路径中,所有边都大于DDD
现在给定图和KKK,问你是否找得到一个满足条件的DDD,如果找得到,输出最小的DDD. 否则输出−1-1−1.
分析
容易知道,相同权值的边要么不在任何组内部,要么全都在同一组点里面。假如相同权值的边,有的在组内,有的在组外的话,这个DDD值肯定只会更大不会更小。
那么贪心思路显而易见了,将所有边按权值升序排序,使用并查集,从左往右,将所有权值相同的边的点合并。然后统计并查集数量,更新答案。也就是在保证“相同权值的边要么不在任何组内部,要么全都在同一组点里面”这个性质的前提下寻找能否分为KKK组。而要使DDD尽可能小,应让处于组内的边尽可能小,所以使用升序。
代码
#include <bits/stdc++.h>
#define fors(i, a, b) for(int i = (a); i <= (b); ++i)
#define lson k<<1
#define rson k<<1|1
#define pb push_back
#define pii pair<int, int>
#define lowbit(x) ((x)&(-(x)))
#define mem(a) memset(a, 0, sizeof(a))
#define DDLC_ESCAPE_PLAN_FAILED ios::sync_with_stdio(false), cin.tie(0)
// #define int long long
const int inf = 0x3f3f3f3f;
const double dinf = 1e100;
typedef long long ll;
//const ll linf = 9223372036854775807LL;
// const ll linf = 1e18;
using namespace std;
const int maxn= 100000 + 5;
int fa[maxn];
struct edge{int l, r, val;bool operator < (const edge& b)const{return val < b.val;}
};
vector<edge> e;
inline int find(int x)
{if(fa[x] == x) return x;return fa[x] = find(fa[x]);
}
bool join(int x, int y)
{int ans = 0;int fx = find(x), fy = find(y);if(fx == fy) return 0;fa[fy] = fx;return 1;
}
signed main()
{DDLC_ESCAPE_PLAN_FAILED;int t;cin >> t;while(t--){e.clear();int n, m, k;cin >> n >> m >> k;fors(i, 1, n) fa[i] = i;int u, v, c;fors(i, 1, m){cin >> u >> v >> c;e.pb({u, v, c});}sort(e.begin(), e.end());int now = n; // 并查集数量,初始为nbool flag = 0;int ans = 0;for(int i = 0; i < m; ++i){if(i == 0 || e[i].val != e[i - 1].val){if(now == k) break;}if(!join(e[i].l, e[i].r)) continue;now--;ans = e[i].val;}cout << (now == k ? ans : -1) << endl;}return 0;
}
HDU6957 Maximal submatrix
题意
给出一个矩阵,要你找一个最大的子矩阵,要求这个子矩阵每一列从上往下都是单调不下降序列。输出最大子矩阵的面积
分析
悬线法,将每个不比上面的元素小的元素标记,然后用这些标记过的元素组成子矩阵。接下来使用悬线dp即可。需要注意的是,子矩阵的最上面一行是可以不被标记的。
代码
(比赛时自己凹的二维dp一直超时,应该是复杂度超过O(n2)O(n^2)O(n2)了)
第一次接触到悬线法,代码可能相对繁琐
#include <bits/stdc++.h>
#define fors(i, a, b) for(int i = (a); i <= (b); ++i)
#define lson k<<1
#define rson k<<1|1
#define pb push_back
#define lowbit(x) ((x)&(-(x)))
#define mem(a) memset(a, 0, sizeof(a))
#define DDLC_ESCAPE_PLAN_FAILED ios::sync_with_stdio(false), cin.tie(0)
// #define int long long
const int inf = 0x3f3f3f3f;
const double dinf = 1e100;
typedef long long ll;
//const ll linf = 9223372036854775807LL;
// const ll linf = 1e18;
using namespace std;
const int maxn = 2005;
bool v[maxn][maxn];
int l[maxn][maxn];
int r[maxn][maxn];
int u[maxn][maxn];
signed main()
{DDLC_ESCAPE_PLAN_FAILED;int t;cin >> t;while(t--){mem(v), mem(l), mem(r), mem(u);int n, m;cin >> n >> m;fors(i, 1, n){fors(j, 1, m){cin >> u[i][j];l[i][j] = j;r[i][j] = j;}}fors(i, 1, n){fors(j, 1, m){if(i == 1 || u[i][j] >= u[i - 1][j]){v[i][j] = 1;}}}fors(i, 1, n){fors(j, 2, m){if(v[i][j] && v[i][j - 1]) l[i][j] = l[i][j - 1];}for(int j = m - 1; j >= 1; --j){if(v[i][j] && v[i][j + 1]) r[i][j] = r[i][j + 1];}}mem(u);fors(i, 1, n){fors(j, 1, m) u[i][j] = 1;}int ans = 0;fors(i, 1, n){fors(j, 1, m){if(v[i][j] && v[i - 1][j]){l[i][j] = max(l[i - 1][j], l[i][j]);}if(v[i][j]) u[i][j] = u[i - 1][j] + 1;}for(int j = m; j >= 1; --j){if(v[i][j] && v[i - 1][j]){r[i][j] = min(r[i - 1][j], r[i][j]);}}}fors(i, 1, n){fors(j, 1, m){ans = max(ans, u[i][j] * (r[i][j] - l[i][j] + 1));}}cout << ans << endl;}return 0;
}
HDU6955 Xor sum
题意
给一个整数数组,你需要找到最短的区间,其按位异或和不小于kkk. 如果有多个,找出左端点最左的
分析
先转化一下。异或运算里,任意xxx的逆元是xxx本身,故对于前缀和pre[i]pre[i]pre[i],pre[j]pre[j]pre[j],iii到jjj的异或和可以表示为pre[i]pre[i]pre[i]^pre[j]pre[j]pre[j].
这之后,直接存异或和,问题转化为:找到两个相距最近的i,ji,ji,j,其异或和不小于kkk.
枚举右端点,然后可能的左端点用TrieTrieTrie树维护,从左到右找,每次找到一个可能的编号就覆盖一下,这样能保证最后找到的是最右边的。不过也可以直接保存最右边的节点。
以后千万不要看着std调试代码,调着调着就调得跟std一模一样了
不过说白了也是之前从来没用过trie吧orz,根本不熟
代码
/*** @file :vsDebug.cpp* @brief :* @date :2021-07-21* @Motto :Love Sakurai Yamauchi Forever*/
#include <bits/stdc++.h>
#define fors(i, a, b) for(int i = (a); i <= (b); ++i)
#define lson k<<1
#define rson k<<1|1
#define pb push_back
#define lowbit(x) ((x)&(-(x)))
#define mem(a) memset(a, 0, sizeof(a))
#define DDLC_ESCAPE_PLAN_FAILED ios::sync_with_stdio(false), cin.tie(0)
// #define int long long
const int inf = 0x3f3f3f3f;
const double dinf = 1e100;
typedef long long ll;
//const ll linf = 9223372036854775807LL;
// const ll linf = 1e18;
using namespace std;
const int maxn = 1e5 + 10;
const int mnx = (1LL << 24) + 10;
int p[mnx][2], res[mnx], a[maxn];
signed main()
{DDLC_ESCAPE_PLAN_FAILED;int t;cin >> t;while(t--){int n, k;cin >> n >> k;fors(i, 1, n){cin >> a[i];a[i] ^= a[i - 1]; // 只存前缀和}int l = -1, r = n, ans = 1;res[1] = -1;p[1][0] = p[1][1] = 0; // initfors(i, 0, n){int x = 1;int tmp = -1;for(int j = 29; j >= 0; --j){if(!x) break;int u = (a[i] >> j) & 1; // 从上往下第j位if(!((k >> j) & 1)){if(p[x][u ^ 1]){tmp = max(tmp, res[p[x][u ^ 1]]);}x = p[x][u];}else x = p[x][u ^ 1];}if(x) tmp = max(tmp, res[x]);if(tmp >= 0 && i - tmp < r - l) l = tmp, r = i;x = 1;for(int j = 29; j >= 0; --j){int u = (a[i] >> j) & 1;if(!p[x][u]){ans++;p[x][u] = ans, res[ans] = -1;p[ans][0] = p[ans][1] = 0;}x = p[x][u];res[x] = max(res[x], i);}}if(l >= 0) cout << l + 1 << ' ' << r << endl;else cout << -1 << endl;}return 0;
}
2021“MINIEYE杯”中国大学生算法设计超级联赛(1)个人解题报告相关推荐
- 【2021杭电多校赛】2021“MINIEYE杯”中国大学生算法设计超级联赛(3)签到题3题
2021"MINIEYE杯"中国大学生算法设计超级联赛(3) Start Time : 2021-07-27 12:00:00 End Time : 2021-07-27 17:0 ...
- 【2021杭电多校赛】2021“MINIEYE杯”中国大学生算法设计超级联赛(1)签到题15869
2021"MINIEYE杯"中国大学生算法设计超级联赛(1) Start Time : 2021-07-20 12:10:00 End Time : 2021-07-20 17:1 ...
- 2021“MINIEYE杯”中国大学生算法设计超级联赛
2021"MINIEYE杯"中国大学生算法设计超级联赛 1006 Given a sequence of integers of length n, find the shorte ...
- 2021“MINIEYE杯”中国大学生算法设计超级联赛(2)
2021"MINIEYE杯"中国大学生算法设计超级联赛(2) 1008 I love exam (类背包DP) 1010 I love permutation (数学构造,剩余系) ...
- 7068 Dota2 Pro Circuit 杭电多校(2021“MINIEYE杯”中国大学生算法设计超级联赛9) [贪心+双指针]
题目 Dota2 Pro Circuit *Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Oth ...
- 【2021杭电多校赛】2021“MINIEYE杯”中国大学生算法设计超级联赛(5)签到题4题
Solved Pro.ID Title Ratio(Accepted / Submitted) 1001 Miserable Faith 33.33%(19/57) 1002 String Mod 2 ...
- 【2021杭电多校赛】2021“MINIEYE杯”中国大学生算法设计超级联赛(8)
1006 GCD Game (博弈论,nim游戏,质因子个数) 题意:有n个数a1,a2....an两个人玩游戏,Alice先动,Bob后动每次可以将一个数变为他的因子,直到不能动就输了. 题解:将问 ...
- 2021“MINIEYE杯”中国大学生算法设计超级联赛(8)(1002,1004,1006,1009)
前言 依旧是白嫖账号,只打了一些题/kk 正题 1002 Buying Snacks 题目大意 nnn个物品,每个可以买一次也可以不买,如果买需要选择1/21/21/2块钱的,然后也可以相邻两个一起买 ...
- 2021“MINIEYE杯”中国大学生算法设计超级联赛(7)部分题解
前言 找大佬嫖到个号来划水打比赛了,有的题没写或者不是我写的就不放了. 目前只有:1004,1005,1007,1008,1011 正题 题目链接:https://acm.hdu.edu.cn/con ...
最新文章
- python -socket -client
- redis持久化方案
- Elmah 日志记录组件
- 乐观锁、悲观锁简单分析,回忆旧(新)知识...
- Linux系统挂载操作mount详解
- nginx主模块指令
- linux grub rescue 光盘,Ubuntu9.10用安装光盘如何进入linux rescue方式?
- sqlserver 插入数据时异常,仅当使用了列列表并且 IDENTITY_INSERT 为 ON 时,才能为表'XXXXX.dbo.XXXXXXXXX'中的标识列指定显式值。...
- jenkins 忘记用户名和密码
- RFID芯片有什么用
- EFCore 调试远程SqlServer数据库提示信号灯超时时间已到
- 局域网SDN技术硬核内幕 一 分布式任意播网关
- Typecho网站访问浏览总量统计插件PageViews升级版
- SPSS——连续变量的描述统计
- python 负数索引
- “衣带渐宽终不悔,为伊消得人憔悴”的赏析
- PHP动态网站开发期末试卷,《PHP动态网站开发实例教程》课程考核方案
- 计算机cpu执行时间 指令条数的单位,计算机原理2015年10月真题(02384)
- Node版本管理工具
- 2021年山东省职业院校技能大赛中职组网络安全赛项竞赛样题