2022杭电多校(一)
2022杭电多校(一)
文章目录
- 2022杭电多校(一)
- 一、比赛小结
- 二、题目分析及解法(基础题)
- 1001、String
- 1002、Dragon slayer
- 1003、BackPack
- 1004、Ball
- 1009、Laser
- 1011、Random
- 1012、Alice and Bob
- 三、题目分析及解法(进阶题)
- 1004、Path
- 1005、Grammar
- 1006、Travel plan
- 1007、Treasure
- 1008、Walk
一、比赛小结
比赛链接:2022杭电多校 (hdu.edu.cn)
二、题目分析及解法(基础题)
1001、String
题目链接:Problem - 7138 (hdu.edu.cn)
题意:
有一串长度 n ( n ≤ 1 0 6 ) n \ (n\le 10^6) n (n≤106) 的字符串,我们定义关于 G G G 的函数 F G F_G FG 为满足以下条件的正整数 x x x 的数量:
1 ≤ x ≤ G l e n 1\le x\le G_{len} 1≤x≤Glen
G [ 1 , x ] = G [ G l e n − x + 1 , G l e n ] G[1,x]=G[G_{len}−x+1,G_{len}] G[1,x]=G[Glen−x+1,Glen]
区间 [ 1 , x ] [1,x] [1,x] 和 [ G l e n − x + 1 , G l e n ] [G_{len}−x+1,G_{len}] [Glen−x+1,Glen] 的 LCS 长度大于 0 并且可被 k 整除
求 ∏ i = 1 n ( F S [ 1 , … , i ] + 1 ) ( m o d 998244353 ) \displaystyle \prod_{i=1}^n(F_{S[1,\dots,i]}+1) \pmod {998244353} i=1∏n(FS[1,…,i]+1)(mod998244353)
题解:
其实是一道简单的字符串题目,但比赛时过的人很少,我们考虑 [ 1 , n ] [1,n] [1,n] 和 [ i , n ] [i,n] [i,n] 的最长公共前缀,exkmp 可以快速求出。并设为 [ 1 , x ] [1,x] [1,x] 和 [ i , i + x − 1 ] [i,i+x-1] [i,i+x−1] ,那么考虑其交叉部分,即 [ i , x ] [i,x] [i,x] 。我们发现可以截取出 [ i , i − 1 + t ∗ k ] [i,i-1+t*k] [i,i−1+t∗k] ,那么考虑其贡献,为 a n s [ ] ans[] ans[] 数组进行贡献 +1 ,朴素实现会超时,利用模 k 意义下的差分即可解决。
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 998244353;
const int maxn = 1e6 + 5;
int n, k;
int res[maxn];
int exnext[maxn];
char s[maxn];
void getexnext() {int i = 0, j, pos;exnext[0] = n;while (s[i] == s[i + 1] && i + 1 < n) i++;exnext[1] = i;pos = 1;for (i = 2; i < n; i++) {if (exnext[i - pos] + i < exnext[pos] + pos)exnext[i] = exnext[i - pos];else {j = exnext[pos] + pos - i;if (j < 0) j = 0;while (i + j < n && s[j] == s[j + i]) j++;exnext[i] = j;pos = i;}}
}
signed main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int _;cin >> _;while (_--) {cin >> s;cin >> k;n = strlen(s);memset(res, 0, sizeof res);getexnext();for (int i = 0; i < n; i++)if (exnext[i] >= i - 1 + k) {int p1 = 2 * i - 1 + k;int len = (exnext[i] - i) / k * k;if (p1 < n) res[p1]++;if (p1 + len < n) res[p1 + len]--;}int ans = 1;for (int i = 0; i < n; i++) {ans = (ans * (res[i] + 1)) % mod;if (i + k < n) res[i + k] += res[i];}cout << ans << endl;}return 0;
}
1002、Dragon slayer
题目链接:Problem - 7139 (hdu.edu.cn)
题意:
有一个 n × m n\times m n×m 的长方形区域,英雄要去屠龙,但区域内有些墙壁,英雄可以让一堵墙永远消失,英雄想知道,至少使用几次超能力,可以屠龙。
题解:
这里的 n 、 m n、m n、m 都小于 15 ,乱搞就行, BFS + 状压
代码:
#include <bits/stdc++.h>
#define pii pair<int, int>
using namespace std;const int dx[] = {0, 0, 1, -1};
const int dy[] = {1, -1, 0, 0};
int n, m, k;
int xs, xt, ys, yt;
int res;
struct e {int x1, y1, x2, y2;
} edge[20];
bool ans[20][20];bool judge(int x1, int y1, int x2, int y2, int state) {if (x1 == x2) {if (y1 > y2) swap(y1, y2);for (int i = 0; i < k; i++)if (!(state & (1 << i)) && y2 == edge[i].y1 &&(edge[i].x1 <= x1 && x1 < edge[i].x2))return true;}if (y1 == y2) {if (x1 > x2) swap(x1, x2);for (int i = 0; i < k; i++)if (!(state & (1 << i)) && x2 == edge[i].x1 &&(edge[i].y1 <= y1 && y1 < edge[i].y2))return true;}return false;
}bool bfs(int state) {queue<pii> q;q.push({xs, ys});while (!q.empty()) {pii cur = q.front();q.pop();int xx = cur.first, yy = cur.second, nx, ny;for (int i = 0; i < 4; i++) {nx = xx + dx[i], ny = yy + dy[i];if (nx < 0 || nx >= n || ny < 0 || ny >= m || ans[nx][ny]) continue;if (!judge(xx, yy, nx, ny, state)) {ans[nx][ny] = true;q.push({nx, ny});}}}return ans[xt][yt];
}int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int _;cin >> _;while (_--) {cin >> n >> m >> k;cin >> xs >> ys >> xt >> yt;res = k;for (int i = 0; i < k; i++)cin >> edge[i].x1 >> edge[i].y1 >> edge[i].x2 >> edge[i].y2;for (int state = 0; state < (1 << k); state++) {int cnt = 0, tmp = state;while (tmp) {if (tmp & 1) cnt++;tmp >>= 1;}if (cnt >= res) continue;memset(ans, false, sizeof ans);ans[xs][ys] = true;if (bfs(state)) res = cnt;}cout << res << endl;}return 0;
}
1003、BackPack
题目链接:Problem - 7140 (hdu.edu.cn)
题意:
有 n 个物品和一个容量为 m 的背包,每个物品有两个属性:体积 v 和 价值 w ,问:是否存在一种选择方案使得所选物品的体积总和等于背包容量,如果存在,那么这些背包物品的价值的最大异或和是多少
题解:
一道略微复杂的 dp题,朴素做法是,令 d p i , j , k dp_{i,j,k} dpi,j,k 为考虑前 i i i 个物品,体积为 j j j ,异或和为 k k k 的方案是否存在,那么有
d p [ i + 1 ] [ j ] [ k ] = d p [ i + 1 ] [ j ] [ k ] ∣ d p [ i ] [ j − v [ i + 1 ] ] [ k ⊕ v [ i + 1 ] ] dp[i+1][j][k]=dp[i+1][j][k]\ |\ dp[i][j-v[i+1]][k\oplus v[i+1]] dp[i+1][j][k]=dp[i+1][j][k] ∣ dp[i][j−v[i+1]][k⊕v[i+1]]
然后就可以利用 Biteset 暴力优化来解决这道题,也有的做法是用 set 来优化暴力 2022"杭电杯"中超联赛·第一场 - CarryNotKarry
实际操作时,是令 f i , j , k f_{i,j,k} fi,j,k 表示前 i i i 个物品,异或和为 j j j ,体积为 k k k 的情况是否存在,那么有 f i + 1 , j = f i , j ∨ ( f i , j ⊕ v i + 1 < < w i ) f_{i+1,j}=f_{i,j}\lor (f_{i,j\oplus v_{i+1}}<<w_i) fi+1,j=fi,j∨(fi,j⊕vi+1<<wi) ,然后配合滚动数组和 Bitset
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1050;
int n, m;
int v[maxn], w[maxn];
bitset<1050> f[maxn], g[maxn]; // 滚动数组,节省开支
int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int _;cin >> _;while (_--) {cin >> n >> m;int ans = -1;for (int i = 0; i < 1024; ++i) f[i].reset();for (int i = 1; i <= n; i++) cin >> v[i] >> w[i];f[0][0] = 1;for (int i = 1; i <= n; i++) {for (int j = 0; j < 1024; j++) g[j] = (f[j] << v[i]);for (int j = 0; j < 1024; j++) f[j] |= g[j ^ w[i]];}for (int i = 0; i < 1024; i++)if (f[i][m]) ans = i;cout << ans << endl;}return 0;
}
1004、Ball
题目链接:Problem - 7141 (hdu.edu.cn)
题意:
在 m × m m\times m m×m 的棋盘上有 n ( n ≤ 2000 ) n \ (n\le 2000) n (n≤2000) 个点,现在问你,有多少种选法,可以选出三个点,使其组成的三角形(可退化)的中间大小的边的长度是素数 (此处使用切比雪夫距离)
题解:
其实也是一道简单题,但现场赛只有50+过了,不过做题时也确实有些精巧的黑科技。考虑到 n n n 比较小,可以先求出两两距离,然后先选取出两个点,使其长度为素数,然后再找一个点,使得这个点可以补出较长边和较短边。具体实现可以通过 bitset 来搞。
代码:
#include <bits/stdc++.h>
#define int long long
#define pii pair<int, int>
using namespace std;
const int maxn = 2020;
const int maxm = 200020;
int n, m;int prime[maxm], pn;
bool isp[maxm];
void table() {pn = 0;memset(isp, true, sizeof isp);isp[0] = isp[1] = false;for (int i = 2; i < maxm; i++) {if (isp[i]) prime[pn++] = i;for (int j = 0; j < pn && (i * prime[j] < maxm); j++) {isp[i * prime[j]] = false;if (i % prime[j] == 0) break;}}
}pii p[maxn];
int d(pii a, pii b) {return abs(a.first - b.first) + abs(a.second - b.second);
}
struct edge {int a, b;int dis;
} e[maxn * maxn];bitset<2020> dis[maxn];
signed main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int _;cin >> _;table();while (_--) {cin >> n >> m;for (int i = 1; i <= n; i++) dis[i].reset();for (int i = 1; i <= n; i++) cin >> p[i].first >> p[i].second;int cnt = 0;for (int i = 1; i <= n; i++)for (int j = i + 1; j <= n; j++) e[cnt++] = {i, j, d(p[i], p[j])};sort(e, e + cnt, [](edge u, edge v) { return u.dis < v.dis; });int ans = 0;for (int i = 0; i < cnt; i++) {if (isp[e[i].dis]) ans += (dis[e[i].a] ^ dis[e[i].b]).count();dis[e[i].a][e[i].b] = 1;dis[e[i].b][e[i].a] = 1;}cout << ans << endl;}return 0;
}
1009、Laser
题目链接:Problem - 7146 (hdu.edu.cn)
题意:
在二维平面有 n n n 个敌人,激光武器可以发射米字型射线,问是否可以只用一个武器来摧毁所有敌人
题解:
这道题挺暴力的,给出两个敌人就可以大致确定范围(12个可选内容),然后对可选范围进行枚举即可,答案提供了另一个角度,就是先由一个点确定一条直线,再由另外另一个点确定这条线上的三个交点是否合法。实际上这两个思路殊途同归,都是讨论了 12 个可选点的合法情况。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 6;
int x[maxn], y[maxn], a[maxn], b[maxn];
int n;
bool pd(int x, int y) {if (x == 0 || y == 0 || x == y || x + y == 0) return true;return false;
}
bool check(int xx, int yy) {for (int i = 1; i <= n; ++i)if (!pd(xx - x[i], yy - y[i])) return false;return true;
}
bool check() {bool flag = true;int xx = x[1], yy = y[1];for (int i = 2; i <= n; ++i) {if (x[i] == xx) continue;flag = false;if (check(xx, y[i])) return true;if (check(xx, y[i] + (x[i] - xx))) return true;if (check(xx, y[i] - (x[i] - xx))) return true;break;}if (flag) return true;return false;
}
int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);int _;cin >> _;while (_--) {cin >> n;for (int i = 1; i <= n; ++i) cin >> a[i] >> b[i];for (int i = 1; i <= n; ++i) x[i] = a[i], y[i] = b[i];if (check()) {puts("YES");continue;}for (int i = 1; i <= n; ++i) x[i] = b[i], y[i] = a[i];if (check()) {puts("YES");continue;}for (int i = 1; i <= n; ++i) x[i] = a[i] + b[i], y[i] = a[i] - b[i];if (check()) {puts("YES");continue;}for (int i = 1; i <= n; ++i) x[i] = a[i] - b[i], y[i] = a[i] + b[i];if (check()) {puts("YES");continue;}puts("NO");}return 0;
}
1011、Random
题目链接:Problem - 7148 (hdu.edu.cn)
题意:
N数字,随机生成[0,1] ,做M操作, 1 2 \frac{1}{2} 21 概率删除最大值, 1 2 \frac{1}{2} 21 概率删除最小值, 计算期望值,模 1 0 9 + 7 10^9+7 109+7
题解:
输出 1 2 × ( N − M ) ( m o d 2 ) \frac{1}{2}\times (N-M) \pmod 2 21×(N−M)(mod2) 即可
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 1e9 + 7;
const int inv2 = (mod + 1) / 2;
int n, m;
signed main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int _;cin >> _;while (_--) {cin >> n >> m;cout << (n - m) * inv2 % mod << endl;}return 0;
}
1012、Alice and Bob
题目链接:Problem - 7149 (hdu.edu.cn)
题意:
Alice 和 Bob 在玩游戏,规则为:初始时黑板上 m 个数字,分别位于 1 ∼ n 1\sim n 1∼n 之间,如果黑板上还有数字,并且没有带值的数字0在黑板上,Alice 可以将黑板上剩余的数字分成两组。Bob 选择其中一组并擦除该组中的所有数字。然后将所有剩余的数字减去一。
在任何时候,如果有一个值为0在黑板上,Alice 获胜;否则,如果黑板上的所有数字都被擦除,则Bob 获胜。 请确定如果爱丽丝和鲍勃都以最佳方式玩游戏,谁将赢得游戏。
题解:
对于 Alice 而言,最优策略是“对半分”,即尽量将每个相同的数都对分到两个组里,这样,对于数字 i i i ,如果它的个数为 a [ i ] a[i] a[i] 个,那么它想要减到 0 0 0 则至少需要 log i \log i logi 步,只要存在某个 i i i ,使得 a [ i ] ≥ ( 1 < < log i ) a[i]\ge (1<<\log i) a[i]≥(1<<logi) 即可。
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 1e6 + 6;
int n;
int a[maxn], sum[maxn];
signed main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int _;cin >> _;while (_--) {cin >> n;for (int i = 0; i <= n; i++) cin >> a[i];sum[n] = a[n];for (int i = n - 1; i >= 0; i--) sum[i] = a[i] + sum[i + 1] / 2;if (sum[0])cout << "Alice\n";elsecout << "Bob\n";}return 0;
}
三、题目分析及解法(进阶题)
还不太会(
1004、Path
1005、Grammar
1006、Travel plan
1007、Treasure
1008、Walk
2022杭电多校(一)相关推荐
- 2022杭电多校赛第八场
2022杭电多校赛第八场 文章目录 2022杭电多校赛第八场 1004.Quel'Thalas 1001.Theramore 1011.Stormwind 1008.Orgrimmar 1005.Ir ...
- 2022杭电多校第八场题解
2022杭电多校第八场 Theramore(思维) 题意 给定一个01字符串,每次可以将一个奇数长度的区间翻转,求操作后字典序最小的字符串. 分析 翻转奇数长度的区间,元素位置的奇偶性不变,统计奇数位 ...
- 2022杭电多校(十)
2022杭电多校(十) 文章目录 2022杭电多校(十) 一.比赛小结 二.题目分析及解法(基础题) 1001.Winner Prediction 1003.Wavy Tree 1004.Averag ...
- 2022杭电多校(九)
2022杭电多校(九) 文章目录 2022杭电多校(九) 一.比赛小结 二.题目分析及解法(基础题) 1001.Arithmetic Subsequence 1003.Fast Bubble Sort ...
- 2022杭电多校(二)
2022杭电多校(二) 文章目录 2022杭电多校(二) 一.比赛小结 二.题目分析及解法(基础题) 1001.Static Query on Tree 1002.C++ to Python 1003 ...
- 2022杭电多校(四)
2022杭电多校(四) 文章目录 2022杭电多校(四) 一.比赛小结 二.题目分析及解法(基础题) 1001.Link with Bracket Sequence II 1002.Link with ...
- 2022杭电多校(五)
2022杭电多校(五) 文章目录 2022杭电多校(五) 一.比赛小结 二.题目分析及解法(基础题) 1003.Slipper 1006.BBQ 1007.Count Set 1010.Braggin ...
- 2022杭电多校(三)
2022杭电多校(三) 文章目录 2022杭电多校(三) 一.比赛小结 二.题目分析及解法(基础题) 1001.Equipment Upgrade 1002.Boss Rush 1003.Cyber ...
- 2022杭电多校八 1011-Stormwind(贪心)
题目链接:杭电多校8 - Virtual Judge 题意:一个n*m的长方形,可以沿水平或竖直方向画若干条线,每条线的两端点都在长方形边界上,且线要与长方形的某一边平行且端点位于格点上.要求这些线划 ...
最新文章
- matlab怎么调用DeepLearn,使用DeepLearnToolbox-master中DBN工具箱做数据分类出现问题,求......
- InfoVista.NET 内部数据格式简介
- RabbitMQ fanout交换机(消费者)
- http的请求方法 GET、HEAD、POST、PUT、DELETE、CONNECT、OPTIONS、TRACE 说明
- android 录音原始文件_5分钟短文 | Android证书生成,签名,验证,虽然难,但学一次就够了!...
- Docker安装部署ELK教程 (Elasticsearch+Kibana+Logstash)
- redis的密码验证,及哨兵的相关配置
- 通信基站c语言,[转]2015年数学建模C题–基于无线通信基站的室内三维定位问题...
- java两个对象赋值_一起学Java(二十六)----- 对象之间赋值
- CTime类,CTime 与 CString转换
- [leetcode] 24. Swap Nodes in Pairs
- unity素材三:未来城市场景
- 新手建站推广完美教程(重点推荐)
- java 批量修改图片名称_java 批量修改文件名称
- dede 表单必填_织梦给自定义表单增加必填功能,织梦表单必填设置
- php 二维数组变一维数组,php中怎么将二维数组转为一维数组
- Windows网络共享或共享打印机无法访问连接的简单终极解决方法
- 谷歌浏览器无法下载东西未响应的问题
- 热天的阅读日志,真的好热
- 移动磁盘已用空间0字节要如何办啊
热门文章
- 电子信息、通信、电类专业将会遇到的面试题大全
- C++设计原则——迪米特法则
- .mdf和.ldf是什么文件
- 编译linux内核生成.ko,Linux内核编译完整过程
- js页面跳转和新窗口打开
- ChatGPT 开始摧毁在线教育公司;与苹果、迪士尼和网飞纠纷中美国编剧协会罢工;英伟达将在今年进行 IPO;深度学习之父从谷歌离职;硅谷银行破产报告……《经济学人 | 第 19周》
- oracle数据长度超过4000,有没有办法,突破VARCHAR2最大长度是4000的限制
- 【IoT】交互式智能多功能插排设计
- 【每日最爱一句】2013.06.18
- ros_control控制真实电机的方法