2020杭電多校第四場題解
阿新 • • 發佈:2020-07-31
2020 Multi-University Training Contest 4
施工中。。。
1002 Blow up the Enemy
#include<bits/stdc++.h> #define ll long long #define maxn 100010 #define mod 1000000007 using namespace std; int main() { int t; scanf("%d", &t); while (t--) { int n; scanf("%d", &n); int sum = 0, ma = 1e9; for (int i = 0; i < n; i++) { int x, y; scanf("%d%d", &x, &y); int tp = ((100 + x - 1) / x - 1) * y; if (tp < ma) ma = tp, sum = 1; else if (tp == ma) sum++; } printf("%.8lf\n", 1.0 - 0.5 * sum / n); } return 0; }
1003 Contest of Rope Pulling
#include<bits/stdc++.h> #define ll long long #define maxn 300010 #define mod 1000000007 using namespace std; ll dp[maxn]; ll inf = -1e15; struct cv { ll x, y; }a[maxn], b[maxn], c[maxn]; bool cmp(cv p, cv q) { return p.y > q.y; } int main() { int t; scanf("%d", &t); while (t--) { int n, m; scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) scanf("%lld%lld", &a[i].x, &a[i].y); for (int i = 0; i < m; i++) scanf("%lld%lld", &b[i].x, &b[i].y); random_shuffle(a, a + n); random_shuffle(b, b + m); int cnt = 0; for (int i = 0; i < min(n, m); i++) { c[cnt++] = a[i]; b[i].x *= -1; c[cnt++] = b[i]; } if (n > m) for (int i = m; i < n; i++) c[cnt++] = a[i]; else for (int i = n; i < m; i++) { b[i].x *= -1; c[cnt++] = b[i]; } for (int i = 0; i < maxn; i++) dp[i] = inf; dp[maxn / 2] = 0; for (int i = 0; i < cnt; i++) { if (c[i].x > 0) { for (ll j = maxn - 1; j - c[i].x >= 0; j--) { dp[j] = max(dp[j], dp[j - c[i].x] + c[i].y); } } else { for (ll j = 0; j - c[i].x < maxn; j++) dp[j] = max(dp[j], dp[j - c[i].x] + c[i].y); } } printf("%lld\n", dp[maxn / 2]); } return 0; }
1004 Deliver the Cake
求最短路的模板題,在計算距離的時候處理一下是左手還是右手拿蛋糕就可以了
#include<bits/stdc++.h> #define ll long long #define maxn 200010 #define mod 1000000007 using namespace std; vector<int>b[maxn]; vector<ll>c[maxn]; char a[maxn]; int pe[maxn]; ll ans[maxn][3]; struct cv { int x, pe; ll y; friend bool operator<(cv p, cv q) { return p.y > q.y; } }dd, bb; int main() { int t; scanf("%d", &t); while (t--) { int n, m, s, e; ll x; scanf("%d%d%d%d%lld", &n, &m, &s, &e, &x); scanf("%s", a + 1); for (int i = 1; i <= n; i++) { if (a[i] == 'L') pe[i] = 1; else if (a[i] == 'R') pe[i] = 2; else pe[i] = 3; vector<int>v; swap(v, b[i]); vector<ll>vv; swap(vv, c[i]); ans[i][1] = ans[i][2] = 0; } for (int i = 0; i < m; i++) { int l, r; ll z; scanf("%d%d%lld", &l, &r, &z); b[l].push_back(r); c[l].push_back(z); b[r].push_back(l); c[r].push_back(z); } dd.x = s, dd.y = 0; priority_queue<cv>q; if (pe[s] & 1) { dd.pe = 1; q.push(dd); } if (pe[s] & 2) { dd.pe = 2; q.push(dd); } while (!q.empty()) { dd = q.top(); q.pop(); int now = dd.x; if (dd.y != ans[now][dd.pe]) continue; if (now == e) break; for (int i = 0; i < b[now].size(); i++) { bb.x = b[now][i], bb.y = dd.y + c[now][i]; if ((dd.pe & pe[bb.x]) == 0) { bb.pe = pe[bb.x]; bb.y += x; } else bb.pe = dd.pe; if (ans[b[now][i]][bb.pe] == 0) { ans[b[now][i]][bb.pe] = bb.y; q.push(bb); } else if (ans[b[now][i]][bb.pe] > bb.y) { ans[b[now][i]][bb.pe] = bb.y; q.push(bb); } } } if (ans[e][1] == 0) printf("%lld\n", ans[e][2]); else if (ans[e][2] == 0) printf("%lld\n", ans[e][1]); else printf("%lld\n", min(ans[e][1], ans[e][2])); } return 0; }
1005 Equal Sentences
對於每個相鄰字元不同的串,相鄰的兩個數可以交換,但是不能連續交換
通過 \(dp\) 可以得到,不同的串的個數就是斐波那契數列
計算的時候,連續相同的數階段截斷即可
#include<bits/stdc++.h>
#define ll long long
#define maxn 200010
#define mod 1000000007
using namespace std;
int a[maxn];
ll dp[maxn];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
int t;
cin >> t;
dp[0] = 1;
dp[1] = 1;
for (int i = 2; i < maxn; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
dp[i] %= mod;
}
while (t--) {
int n;
map<string, int>mp;
int cnt = 0;
cin >> n;
for (int i = 1; i <= n; i++) {
string tp;
cin >> tp;
if (mp.count(tp)) a[i] = mp[tp];
else {
mp[tp] = cnt;
a[i] = cnt++;
}
}
ll ans = 1;
ll sum = 1;
for (int i = 2; i <= n; i++) {
if (a[i] == a[i - 1]) {
ans = ans * dp[sum] % mod;
sum = 1;
}
else sum++;
}
ans = ans * dp[sum] % mod;
printf("%lld\n", ans);
}
return 0;
}
1007 Go Running
對於每條記錄,我們令他都是有一個從 \(t=0\) 的時刻就開始跑的人經過的,那這個人可以同時經過的點都是最多的
對於每條記錄,可能會有兩個人,即一個從東向西跑,一個從西向東跑
我們對兩個人建邊,就可以建成一個二分圖
對於每條邊都需要一條個點,即最小點覆蓋
#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
const int MAXN = 200010;
const int MAXM = 200010;
const int INF = 2147483647;
struct Edge {
int v;
int next;
} edge[MAXM];
int nx, ny;
int cnt;
int t;
int dis;
int first[MAXN];
int xlink[MAXN], ylink[MAXN];
/*xlink[i]表示左集合頂點所匹配的右集合頂點序號,ylink[i]表示右集合i頂點匹配到的左集合頂點序號。*/
int dx[MAXN], dy[MAXN];
/*dx[i]表示左集合i頂點的距離編號,dy[i]表示右集合i頂點的距離編號*/
int vis[MAXN]; //尋找增廣路的標記陣列
void init() {
cnt = 0;
memset(first, -1, sizeof(first));
memset(xlink, -1, sizeof(xlink));
memset(ylink, -1, sizeof(ylink));
}
void read_graph(int u, int v) {
edge[cnt].v = v;
edge[cnt].next = first[u], first[u] = cnt++;
}
int bfs() {
queue<int> q;
dis = INF;
memset(dx, -1, sizeof(dx));
memset(dy, -1, sizeof(dy));
for (int i = 0; i < nx; i++) {
if (xlink[i] == -1) {
q.push(i);
dx[i] = 0;
}
}
while (!q.empty()) {
int u = q.front();
q.pop();
if (dx[u] > dis) break;
for (int e = first[u]; e != -1; e = edge[e].next) {
int v = edge[e].v;
if (dy[v] == -1) {
dy[v] = dx[u] + 1;
if (ylink[v] == -1) dis = dy[v];
else {
dx[ylink[v]] = dy[v] + 1;
q.push(ylink[v]);
}
}
}
}
return dis != INF;
}
int find(int u) {
for (int e = first[u]; e != -1; e = edge[e].next) {
int v = edge[e].v;
if (!vis[v] && dy[v] == dx[u] + 1) {
vis[v] = 1;
if (ylink[v] != -1 && dy[v] == dis) continue;
if (ylink[v] == -1 || find(ylink[v])) {
xlink[u] = v, ylink[v] = u;
return 1;
}
}
}
return 0;
}
int MaxMatch() {
int ans = 0;
while (bfs()) {
memset(vis, 0, sizeof(vis));
for (int i = 0; i < nx; i++) if (xlink[i] == -1) {
ans += find(i);
}
}
return ans;
}
int main() {
int tt;
scanf("%d", &tt);
while (tt--) {
init();
int n;
scanf("%d", &n);
map<ll, int>mp1, mp2;
int cntt = 0;
set<ll>mep;
for (int i = 0; i < n; i++) {
ll x, y;
scanf("%lld%lld", &x, &y);
ll tu = x * (1e9 + 1) + y;
if (mep.count(tu)) continue;
else mep.insert(tu);
ll id1, id2;
if (mp1.count(x - y)) id1 = mp1[x - y];
else {
mp1[x - y] = cntt;
id1 = cntt;
cntt++;
}
if (mp2.count(x + y)) id2 = mp2[x + y];
else {
mp2[x + y] = cntt;
id2 = cntt;
cntt++;
}
read_graph(id1, id2);
}
nx = cntt; ny = cntt;
int ans = MaxMatch();
printf("%d\n", ans);
}
return 0;
}
1011 Kindergarten Physics
#include <bits/stdc++.h>
#define db double
using namespace std;
const db g = 6.67430 * 1e-11;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
int t; cin >> t;
while (t--) {
db a, b, d, t;
cin >> a >> b >> d >> t;
cout << d << '\n';
}
return 0;
}
1012 Last Problem
#include<bits/stdc++.h>
#define ll long long
#define maxn 300010
#define mod 1000000007
using namespace std;
int a[2000][2000];
int to[4][2] = { 0,-1,1,0,-1,0,0,1 };
void sol(int n, int x, int y) {
for (int i = 0; i < 4; i++) {
if (a[x + to[i][0]][y + to[i][1]] == n - i - 1) continue;
if (n - i - 1 >= 1) sol(n - i - 1, x + to[i][0], y + to[i][1]);
}
printf("%d %d %d\n", x, y, n);
a[x][y] = n;
}
int main() {
int n;
scanf("%d", &n);
sol(n, 1000, 1000);
return 0;
}