杭电多校4

2024-03-02 08:08
文章标签 杭电多校

本文主要是介绍杭电多校4,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

都打到4了,我才开始补题...

按难度来补吧,太难了(对我来说233)就不补了

Problem L. Graph Theory Homework

题目大意:有一个竞赛图(每对顶点之间都有一条边相连的有向图),n个点,每个点都有一个权重w,从点i到点j的距离为

 ⌊ sqrt( |wi−wj| ) ⌋.让你求从1到n的最短路。

解题思路:⌊sqrt(a)⌋  + ⌊sqrt(b)⌋  >  ⌊sqrt(a + b)⌋,怎么来的我也不知道,能“感觉”到其正确性,所以从1到n的最短路就是直接从1走到n。

AC Code:

#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define pb push_back
#define lowbit(x) x&(-x)
#define PII  pair<int, int> 
#define FAST ios::sync_with_stdio(false)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e5 + 5;
using namespace std;int a[maxn];int main()
{int t; scanf("%d", &t);while(t--){int n; scanf("%d", &n);for(int i = 1; i <= n; i++){scanf("%d", a + i);}int ans = floor(sqrt(abs(a[1] - a[n])));printf("%d\n", ans);}return 0;
}

Problem K. Expression in Memories

题目大意:有一个递归定义“合法表达式”(其实就和我们平常的认知差不多),给一个字符串,里面有一些问号,代表这个位置你可以任意修改成 0123456789+*这些东西,问你能否改成一个合法表达式,不能输出XXX,可以就输出合法的字符串

解题思路:纯模拟题,分类讨论如何修改问号,然后check一下答案是否合理即可

1,把问号改成操作符号(不妨就取+)的情况: ?前面是个0,并且这个0前面是个操作字符(* or +)

2,把问号改成数字(不妨就取1)的情况: else 1

再考虑check的内容:

1,连续的操作字符不行

2,首尾是操作字符、0不行

3,操作字符后面是个0并且这个0的后面不是操作字符,不行

 

AC Code:

#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define pb push_back
#define lowbit(x) x&(-x)
#define PII  pair<int, int> 
#define FAST ios::sync_with_stdio(false)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e5 + 5;
using namespace std;char s[maxn];bool check(char *a){int len = strlen(a);if(s[0] == '+' || s[0] == '*' || s[len-1] == '+' || s[len-1] == '*') return false;for(int i = 0; i < len - 1; i++){if((s[i] == '+' || s[i] == '*') && (s[i+1] == '+' || s[i+1] == '*')) return false;if((i == 0 || s[i-1] == '+' || s[i-1] == '*') && s[i] == '0' && (s[i+1] != '+'  && s[i+1] != '*')) return false;}return true;
}int main()
{int t; scanf("%d", &t);while(t--){scanf(" %s", s);int len = strlen(s);for(int i = 1; i < len; i++){if(s[i] == '?'){if(s[i-1] == '0' && (i == 1 || s[i-2] == '+' || s[i-2] == '*')){s[i] = '+';}}}for(int i = 0; i < len; i++){if(s[i] == '?') s[i] = '1';}if(check(s)) puts(s);else puts("IMPOSSIBLE");}return 0;
}

Problem D. Nothing is Impossible

题目大意:这题开始题意有问题,改了之后变得巨水。一张试卷有n个题目,每个题目ai(有说ai == 1,即正确答案保证只有一个)个正确答案和bi个错误答案,m个学生去考试,他们从中选择s个题目并且保证至少有一个人全对,求出s的最大值。

解题思路:由于只有一个正确答案,那么我们来选择题目肯定是选错误答案少的(这样正确的概率就高)。所以按错误答案的数目排个序,按照学生的人数来考虑,要使在选择1道题的情况下有一个人全对,那么至少有b[1] + 1个学生,以此类推,要使在选择x道题的情况下有一个人全对,至少有(b[1] + 1) * (b[2] + 1) ...*(b[x] + 1),求出最大的x就是最终答案。

不知道队友怎么在不了解题意的情况下搞出来的。。。。神奇

AC Code

#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define pb push_back
#define lowbit(x) x&(-x)
#define PII  pair<int, int> 
#define FAST ios::sync_with_stdio(false)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e5 + 5;
using namespace std;int b[maxn];int main()
{int t; scanf("%d", &t);while(t--){int n, m; scanf("%d %d", &n, &m);for(int i = 1; i <= n; i++) scanf("%*d %d", &b[i]);sort(b + 1, b + n + 1);ll t = 1;int ans = 0;for(int i = 1; i <= n; i++){t *= (b[i] + 1);if(t <= m) ans++;else break;}printf("%d\n", ans);}return 0;
}

Problem E. Matrix from Arrays

题目大意:给你一个长度为l的数组a,定义一种方式,用数组a生成一个无穷矩阵M,然后有Q个询问,每次询问输出一个子矩阵内元素的和。

解题思路:会有一个大小为2L *2L的循环节矩阵,当时打表瞎输出了一发看出来的

杜老师讲的有一个很巧妙的推导循环节的过程,可惜我当时没好好听哎,所以就不作证明了

那么循环节知道了,求解询问就很简单了,用sum[i][j]表示点(i, j)左上角所有元素的和,那么预处理出来sum数组(只需要一个循环节矩阵的就行了),询问(x1, y1), (x2, y2)就变成了求sum[x2][y2] - sum[x1-1][y2] - sum[x2][y1-1] + sum[x1-1][y1-1]

这里求sum[i][j]有个技巧,

sum[i][j] = 

      M[L-1][L-1] * (i / L) * (j / L)
   + M[i%L][L-1] * (j / L)
   + M[L-1][j%L] * (i / L)
   + M[i%L][j%L];

相当于是分块求,还是挺好理解的,学到了

求sum的时候直接在M数组上更新更方便写并且节省了空间复杂度(主要是前者),这里的M表示sum

AC Code:

#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define pb push_back
#define lowbit(x) x&(-x)
#define PII  pair<int, int> 
#define FAST ios::sync_with_stdio(false)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e5 + 5;
using namespace std;ll A[15], M[100][100];
int L;ll cal(int i, int j){if(i < 0 || j < 0) return 0;return M[L-1][L-1] * (i / L) * (j / L)+ M[i%L][L-1] * (j / L)+ M[L-1][j%L] * (i / L)+ M[i%L][j%L];
}int main()
{int t; scanf("%d", &t);while(t--){scanf("%d", &L);for(int i = 0; i < L; i++) scanf("%lld", A + i);int cursor = 0;for(int i = 0; i <= 4 * L; i++){for(int j = 0; j <= i; j++){ M[j][i - j] = A[cursor];cursor = (cursor + 1) % L;}}L *= 2;for(int i = 0; i < L; i++){for(int j = 0; j < L; j++){if(i) M[i][j] += M[i-1][j];if(j) M[i][j] += M[i][j-1];if(i && j) M[i][j] -= M[i-1][j-1];}}int Q; scanf("%d", &Q);while(Q--){int x1, y1, x2, y2;scanf("%d %d %d %d", &x1, &y1, &x2, &y2);ll ans = cal(x2, y2) - cal(x1 - 1, y2) - cal(x2, y1 - 1) + cal(x1 - 1, y1 - 1);printf("%lld\n", ans);}}return 0;
}

 

Oh,还有B和J没补,不管了睡觉xixixi

updating...

==============================================================================================

继续写题吧

Problem J. Let Sudoku Rotate

题目大意:给一个16 *16的数独格子,这些格子又被分为16个4*4的(就是数独就得了)。现在逆时针旋转了几个格子,给出旋转后的样子,让你求最少旋转了多少下得到了这个东西。

解题思路:挺暴力的一个题,当时瞎**算了一下复杂度没敢写。可惜了

暴搜+剪枝就能过。

分析一下如何搜索:dfs枚举每一个小方块的旋转次数(0,1,2,3),再判断该方法能否满足数独规则,如果能就继续

搜索到底(最后一个)并且满足,维护ans最小值即可

其实不是很懂里面的剪枝,时间复杂度也不会算

分析一下如何判断是否满足:用两个二位数组r[i][i] c[i][j]分别表示第i行数字j的出现个数,第i列数字j的出现个数,判断是否大于一即可(在我们的操作下不可能小于1)

事先把'0'-'f'转换成0-15更为方便进行操作

AC Code:

#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define pb push_back
#define lowbit(x) x&(-x)
#define PII  pair<int, int> 
#define FAST ios::sync_with_stdio(false)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e5 + 5;
using namespace std;char s[20];
int G[20][20];
int c[20][20], r[20][20];
int t[5][5];
int ans;int change(char ch){if(isdigit(ch)) return ch - '0';return ch - 'A' + 10;
}void add(int x, int y, int val){for(int i = x * 4; i < (x + 1) * 4; i++){for(int j = y * 4; j < (y + 1) * 4; j++){r[i][G[i][j]] += val, c[j][G[i][j]] += val;}}
}bool check(int x, int y){for(int i = x * 4; i < (x + 1) * 4; i++){for(int j = y * 4; j < (y + 1) * 4; j++){r[i][G[i][j]]--, c[j][G[i][j]]--;t[j-y*4][(x+1)*4-i-1] = G[i][j];}}bool flag = true;for(int i = x * 4; i < (x + 1) * 4; i++){for(int j = y * 4; j < (y + 1) * 4; j++){G[i][j] = t[i-x*4][j-y*4];if((++r[i][G[i][j]] > 1) || (++c[j][G[i][j]] > 1)) flag = false;}}return flag;
}void dfs(int x, int y, int cnt){if(x == 4 && y == 0){ans = min(ans, cnt);return ;}add(x, y, 1);if(cnt >= ans) return;for(int i = 1; i <= 4; i++){if(check(x, y)){if(y == 3) dfs(x + 1, 0, cnt + (i % 4));else dfs(x, y + 1, cnt + (i % 4));}}add(x, y, -1);
}int main()
{int T; scanf("%d", &T);while(T--){for(int i = 0; i < 16; i++){scanf("%s", s);for(int j = 0; j < 16; j++) G[i][j] = change(s[j]);}memset(r, 0, sizeof(r)), memset(c, 0, sizeof(c));ans = inf;dfs(0, 0, 0);printf("%d\n", ans);}return 0;
}

这题真是敲死我了。。。

B那个莫队也不会,不补了略略略(我是真滴菜啊

 

这篇关于杭电多校4的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

杭电多校个人补题

全部感悟。 1.要学会就是分类讨论,比如大于n小于n等于n,什么的。各种特殊情况,要考虑到。 2.要学会根据题意进行讨论 一、第八场: 第一题:cats的k-xor k进制表示。肯定就是a%k a/k%k a/(k*k)%k .... 我们会发现,如果说,在十进制下面 a+b=c的话那么肯定就是在很多进制下面都可以满足题意。 那么我们接着去讨论 a+b<c 和 a+b>c

HDU 4937 (杭电多校 #7 1003题)Lucky Number(瞎搞)

题目地址:HDU 4937 多校的题以后得重视起来。。。每道题都错好多次。。。很考察细节。比如这道。。。。WA了无数次。。。。 这题的思路自己真心想不到。。。这题是将进制后的数分别是1位,2位,3位和更多位的分开来计算。 当是1位的时候,显然只有3到6,此时只能是-1 当是2位的时候,可以转换成一元一次方程求解 当是3位的时候,可以转换成一元二次方程求解 当是4位的时候,此时最多也只有

HDU 4940(杭电多校#7 1006) Destroy Transportation system(瞎搞)

题目地址:HDU 4940 当时这个题一看就看出来了是网络流的最小割,然后就一直在想建图。。然后突然发现,应该要让T集合的数目最少,不然只要有两个,那这两个的每一个都可以跑到S集合,使得T集合变小。那就只能是1个了。然后。。枚举就好了。。但是虽然觉得这么做肯定没错。。但是不敢敲。。因为当时都3个小时了才只有10个队过了。。。后来又想了几遍后觉得这样没错,就写完交上了。果然AC。。。 代码如下:

HDU 4923 (杭电多校 #6 1003题)Room and Moor(公式+栈)

题目地址:HDU 4923 比赛的时候脑残了。。思路完全想出来了。。只不过想出了个根本不可能存在的极端数据,然后一看输入数据是100组,就把自己给否决了。。。sad。。当时就应该大胆试一试的。。。 这个题首先可以把最前面的0和最后面的1去掉,因为这两块总可以用0和1抵消掉。然后中间就分成了10相间的情况,然后根据10相间,可以分成若干组,每一组都是由几个1和几个0组成的。比如说11011011

2019杭电多校第八场 HDU 6685 Rikka with Coin(思维)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6685   题目思路:蓝瘦,居然这么简单..QAQ wa到自闭 10分硬币最多用一个,因为用了俩可以用20分代替 20分硬币最多仨,因为俩不够,对40 60这个样例,用仨20是最省的,四个又不够优秀,四个的话10 20 20 50能凑出更多的数字 50分硬币最多一个,俩可以用1美元代替 这些

2019杭电多校第八场 HDU 6662 Acesrc and Travel(树形DP换根法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6662   题目大意:有两个家伙在博弈,每个家伙都想让自己减对方的值尽可能大,每人走一步直到走不动,走的图是棵树,求最后结果   题目思路:这题给我最大的教训就是..AC前看题解看思路不要看代码!!!!!!!!这个坏习惯导致我昨天白浪费一晚上,每个人的编码习惯不同,稍复杂的题如果没有作者亲自说可

2020杭电多校第一场 Finding a MEX(分块+树状数组,维护MEX)

Problem Description Given an undirected graph G=(V,E). All vertices are numbered from 1 to N. And every vertex u has a value of Au. Let Su={Av│(u,v)∈E}. Also, F(u) equals MEX(minimum excludant) value

2020杭电多校第二场 New Equipments(费用流)

Problem Description Little Q’s factory recently purchased m pieces of new equipment, labeled by 1,2,…,m. There are n workers in the factory, labeled by 1,2,…,n. Each worker can be assigned to no more

2020杭电多校第三场 Triangle Collision(计算几何,坐标翻转,镜像对称)

题意: 一个小球在一个等边三角形内碰撞,碰撞速度不比,方向沿边镜像翻折。求发送 k k k次碰撞需要多少时间 思路: 一开始想着是模拟,然后估摸着最后会形成循环,经过起始点。但是太难模拟了。。 看了题解发现,真的特别巧妙。反射意味着穿过!那么就成了全是等边三角形铺成的平面,已知起点和速度。求经过 k k k条边的最短时间。 这个时间可以二分。 仅考虑平行x轴的边,那就直接用 a b s ⌊

杭电多校第八场 Isomorphic Strings(最小表示法,循环同构)

Problem Description It is preferrable to read the pdf statment. Two strings are called cyclical isomorphic if one can rotate one string to get another one. ‘Rotate’ here means ‘‘to take some consecut