2020百度之星程序设计大赛初赛一
A. Drink (Hdu 6743)
题目大意
给定种饮料,每种无限瓶,每瓶饮料有水分,包含卡路里。
现要求选一种饮料不断喝,求摄入至少水分下,得到的卡路里最小值。
解题思路
一开始没看到只能喝一种饮料考虑DP,结果开场3分钟就破百AC怀疑人生,他们都这么快的吗??
因为只能喝一种就枚举每一种饮料求最小值。
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while (t--) { int n, m; cin >> n >> m; int ans = 1e9 + 7; for (int x, y, i = 1; i <= n; ++i) { cin >> x >> y; ans = min(ans, (int)ceil(m * 1.0 / x) * y); } cout << ans << endl; } return 0; }
B. GPA (Hdu 6744)
题目大意
给你四门总分,告诉你每一门中,成绩对应的绩点关系,问绩点最高是多少。
解题思路
就种情况爆搜就好了。
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; double ans; double ch(int x){ if (x >= 95) return(4.3); if (x >= 90) return(4.0); if (x >= 85) return(3.7); if (x >= 80) return(3.3); if (x >= 75) return(3.0); if (x >= 70) return(2.7); if (x >= 67) return(2.3); if (x >= 65) return(2.0); if (x >= 62) return(1.7); if (x >= 60) return(1.0); return 0; } void solve(int x,int pos,double mark){ if (pos==4){ mark += ch(x); ans = max(ans, mark); return; } if (x >= 95) solve(x-95,pos+1,mark+4.3); if (x >= 90) solve(x-90,pos+1,mark+4.0); if (x >= 85) solve(x-85,pos+1,mark+3.7); if (x >= 80) solve(x-80,pos+1,mark+3.3); if (x >= 75) solve(x-75,pos+1,mark+3.0); if (x >= 70) solve(x-70,pos+1,mark+2.7); if (x >= 67) solve(x-67,pos+1,mark+2.3); if (x >= 65) solve(x-65,pos+1,mark+2.0); if (x >= 62) solve(x-62,pos+1,mark+1.7); if (x >= 60) solve(x-60,pos+1,mark+1.0); solve(x,pos+1,mark); } int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int kase; cin>>kase; for (int ii=1,m; ii <= kase; ii++) { cin>>m; ans = 0; solve(m,1,0); cout<<fixed<<setprecision(1)<<ans<<endl; } return 0; }
C. Dec (Hdu 6745)
题目大意
给定两个正整数,每次操作可以让或减一,直到两个都变为一,问整个过程中,出现互质的情况数的最大值。
解题思路
抽象成平面上的点,左下角,初始点,一次可以向左或向下走一格,互质点有一个贡献,问从到的所有路径中,走到有贡献点的最大值,Dp即可。预处理从(1,1)到所有点最大值。
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; int dp[1002][1002]; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int main(void) { dp[1][1] = 1; for (int i = 1; i <= 1000; ++i) for (int j = 1; j <= 1000; ++j) { if ((i == 1) && (j == 1)) continue; if (i == 1) dp[i][j] = dp[i][j - 1] + (__gcd(i, j) == 1); else if (j == 1) dp[i][j] = dp[i - 1][j] + (__gcd(i, j) == 1); else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + (__gcd(i, j) == 1); } int kase; cin >> kase; for (int a, b, ii = 1; ii <= kase; ii++) { read(a); read(b); write(dp[a][b], '\n'); } return 0; }
D. Civilization (Hdu 6746)
题目大意
看原文吧,就是建城市得粮食得人口派人取工作继续得粮食直到人口达到9问最短的时间。
解题思路
枚举建城市地点然后优先派人口到能取得粮食最多的地方工作,模拟模拟就好了。
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } int dis(int i, int j, int x, int y) { int qwq = abs(i - x) + abs(j - y); return (int)ceil(qwq * 1.0 / 2); } int a[505][505]; int n; int dx[24] = {0, -1, 0, 1, -2, -1, 0, 1, 2, -3, -2, -1, 1, 2, 3, -2, -1, 0, 1, 2, -1, 0, 1, 0}; int dy[24] = {3, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -2, -2, -2, -3}; int up[9] = {0, 1 * 1 * 8, 2 * 2 * 8, 3 * 3 * 8, 4 * 4 * 8, 5 * 5 * 8, 6 * 6 * 8, 7 * 7 * 8, 8 * 8 * 8}; int solve(int x, int y) { vector<int> qwq; for (int i = 0; i < 24; ++i) { if ((x + dx[i] <= 0) || (x + dx[i] > n) || (y + dy[i] <= 0) || (y + dy[i] > n)) continue; qwq.push_back(a[x + dx[i]][y + dy[i]]); } sort(qwq.begin(), qwq.end(), greater<int>()); int cur = a[x][y]; int people = 1; int ju = 0; size_t len = 0; int tot = 0; int gg = 0; while (people < 9) { gg = (int)ceil((up[people] - tot) * 1.0 / cur); ju += gg; tot += gg * cur; people++; if (len < qwq.size()) { cur += qwq[len]; ++len; } } return ju; } int main(void) { int kase; read(kase); for (int x, y, ii = 1; ii <= kase; ii++) { read(n); read(x); read(y); for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) read(a[i][j]); int ans = 1e9 + 7; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { ans = min(ans, dis(i, j, x, y) + solve(i, j)); } } printf("%d\n", ans); } return 0; }
E. Rotate (Hdu 6747)
题目大意
一个圆环由外到内分成层,第层被分为块,是偶数,一半涂黑色一半涂白色,间隔涂。
现独立旋转每一层,每一层会等概率随机终止一种局面,问黑色联通块个数的期望值。
不降。
解题思路
由于不降,块的长度只会减小,所以第层的黑块至多与与第层的中的一个黑块会有接触,这样有接触之间的黑块连一条边,它们就构成了一个森林。
对于森林,联通块数量 = 点数 - 边数。
由期望的线性性质,E(联通块) = E(点数) - E(边数)
而
对于边数,第层的一个黑块与第层的一个黑块会有接触的概率是
由期望定义知这也是期望边数。
再乘以它们的数量即得
所以
把和代入化简得
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; LL mo = 1e9 + 7; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int inv4 = 250000002; int kase; cin >> kase; for (int ii = 1; ii <= kase; ii++) { int n; cin >> n; int a; cin >> a; if (n == 1) { cout << a / 2 << endl; continue; } else { int b; for (int i = 2; i <= n; ++i) cin >> b; cout << (LL)(a + b) * inv4 % mo << endl; } } return 0; }
F. Matrix (Hdu 6748)
题目大意
给定以原点作为中心的四个正方形,要求从被覆盖的整点中选出个,它们的权值最小。一个点的权值为它到原点的曼哈顿距离乘以被正方形覆盖的次数。
解题思路
qwq
神奇的代码
qwq
G. Mosquito (Hdu 6749)
题目大意
给了一个网格图,一些边缘网格(窗户)有一些蚊子,蚊子每一刻可以上下左右移动一格,不能移出网格,假设网格足够聪明,问最少过多长时间,每个网格都有至少一只蚊子。
解题思路
首先蚊子数少于网格数就直接输出 -1。
考虑逆向,即初始时刻每个位置都有一只蚊子,现在蚊子要飞回窗户,问最少过多长时间,限制就是飞回某一窗户的蚊子数不能多余该窗户原有的蚊子数。
先预处理出每个位置的蚊子飞到每一个窗户所需要的时间。
很显然时间越长,蚊子肯定能飞回窗户,方案可行对时间具有单调性。
二分时间,得到每个蚊子能飞到哪些窗户,再考虑如何分配哪些蚊子飞到哪些窗户,可以看出是带有反悔性的决策,跑一遍网络流即可判断是否可行。
但蚊子数太多,如果我们把每只蚊子与能飞到的窗户连一条边,点数和边数会巨大,我们考虑如何压点。
考虑到蚊子能飞到窗户的情况数最多只有种,于是我们把能飞到窗户的情况相同的蚊子都压成一个点,这样点数就只有。
具体的连边,就是源点与所有情况数连一条边,容量为该情况对应的蚊子数;每种情况与对应的窗户连一条边,容量无限;每个窗户与汇点连一条边,容量是该窗户初始有的蚊子数量。
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; #define MIN(a, b) (((a) < (b) ? (a) : (b))) #define MAX(a, b) (((a) > (b) ? (a) : (b))) template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } #define M 100 #define N 640 const int INF = 233333333; struct data { int to, nxt, flow; } line[N * 2]; int n, m, l, r, ans, team[M * 2], dis[M * 2], head[M * 2], num, u, v, st, en, qaq; void add(int u, int v, int w) { num++; line[num].nxt = head[u]; line[num].to = v; line[num].flow = w; head[u] = num; num++; line[num].nxt = head[v]; line[num].to = u; line[num].flow = 0; head[v] = num; } bool BFS() { int u, v; l = r = 0; team[++r] = st; memset(dis, 0, sizeof(dis)); dis[st] = 1; while (l < r) { u = team[++l]; for (int i = head[u]; i; i = line[i].nxt) { v = line[i].to; if (dis[v] == 0 && line[i].flow) { dis[v] = dis[u] + 1; team[++r] = v; } } } if (dis[en]) return true; else return false; } int DFS(int u, int f) { if (u == en) return f; int tmp = 0; int qwq = 0; int v = 0; for (int i = head[u]; i; i = line[i].nxt) { v = line[i].to; if (dis[v] == dis[u] + 1 && line[i].flow) { qwq = DFS(v, MIN(f - tmp, line[i].flow)); line[i].flow -= qwq; line[i ^ 1].flow += qwq; tmp += qwq; if (tmp == f) return tmp; } } return tmp; } int x[8], y[8], cnt[8]; int k; int ddis[1001][1001][8]; int main(void) { int t; read(t); while (t--) { read(n); read(m); read(k); long long qmq = 0; for (int i = 1; i <= k; ++i) { read(x[i]); read(y[i]); read(cnt[i]); qmq += (long long)cnt[i]; for (int a = 1; a <= n; ++a) for (int b = 1; b <= m; ++b) { ddis[a][b][i] = abs(a - x[i]) + abs(b - y[i]); } } if (qmq < (long long)n * m) { printf("-1\n"); continue; } int tot = (1 << (k)); st = 0; en = tot + k + 1; int l = 0, r = n + m; int cc[66] = {0}; while (l < r) { int mid = (l + r) >> 1; num = 1; for (int i = st; i <= en; ++i) head[i] = 0; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { int sign = 0; for (int a = 1; a <= k; ++a) { if (ddis[i][j][a] <= mid) sign |= (1 << (a - 1)); } cc[sign]++; } } for (int i = 0; i < (1 << k); ++i) { for (int a = 1; a <= k; ++a) if ((i >> (a - 1)) & 1) add(i + 1, tot + a, INF); add(st, i + 1, cc[i]); cc[i] = 0; } for (int i = 1; i <= k; ++i) add(tot + i, en, cnt[i]); int dd = 0; while (BFS()) dd += DFS(st, INF); if (dd < n * m) l = mid + 1; else r = mid; } write(r, '\n'); } return 0; }
H. Function (Hdu 6750)
题目大意
给定,计算
解题思路
参考出处
化公式
从出发。
可用整数分块求,求累加和也可用整数分块求。
至于复杂度为什么会有log不会qwq
神奇的代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; template <typename T> void read(T &x) { int s = 0, c = getchar(); x = 0; while (isspace(c)) c = getchar(); if (c == 45) s = 1, c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); if (s) x = -x; } template <typename T> void write(T x, char c = ' ') { int b[40], l = 0; if (x < 0) putchar(45), x = -x; while (x > 0) b[l++] = x % 10, x /= 10; if (!l) putchar(48); while (l) putchar(b[--l] | 48); putchar(c); } const LL mo = 1e9 + 7; const LL N = 1e6 + 8; bool visit[N]; LL prim[N]; int u[N]; LL sum_mu[N]; void pre_mu() { sum_mu[0] = 0; memset(visit, false, sizeof(visit)); int tot = 0; u[1] = 1; sum_mu[1] = 1; for (int i = 2; i <= N; i++) { if (!visit[i]) { visit[i] = true; prim[++tot] = i; u[i] = -1; } for (int j = 1; j <= tot; j++) { if (prim[j] * i > N) break; visit[prim[j] * i] = true; if (i % prim[j]) u[prim[j] * i] = -u[i]; else { u[prim[j] * i] = 0; break; } } sum_mu[i] = (sum_mu[i - 1] + (LL)u[i] * i % mo + mo) % mo; } } LL inv2 = 500000004; LL calc(LL l, LL r) { LL nxt = 0; LL tmp = 0; while (l <= r) { nxt = r / (r / l); tmp = (tmp + (r / l) * ((l + nxt) % mo) % mo * ((nxt - l + 1) % mo) % mo * inv2 % mo) % mo; l = nxt + 1; } return tmp; } int main(void) { pre_mu(); int kase; read(kase); for (int ii = 1; ii <= kase; ii++) { LL n; LL ans = 0; read(n); LL up = sqrt(n); LL l = 1; LL nxt = 0; while (l <= up) { nxt = (LL)sqrt(n / (n / (l * l))); if (nxt > up) nxt = up; ans = (ans + calc(1, n / (l * l)) * ((sum_mu[nxt] - sum_mu[l - 1] + mo) % mo) % mo) % mo; l = nxt + 1; } write(ans, '\n'); } return 0; }
本文作者:~Lanly~
本文链接:https://www.cnblogs.com/Lanly/p/13360152.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步