7.30 18级杭电多校第四场
文章目录
- 比赛过程
- 题解
- 1002
- 题意
- 解法
- 代码
- 1004
- 题意
- 解法
- 代码
- 1005
- 题意
- 解法
- 代码
- 1007
- 题意
- 解法
- 代码
- 1011
- 题意
- 解法
- 代码
比赛过程
开局被物理题唬住了,以为是个积分题,发现过的人很多,分析之后才发现猫腻,反应有点慢了。1002 wa的比较多,感觉是写法有点繁琐,出现了不容易发现的bug,“水题大作”一直是一个痛点。。。1005也算是个简单题吧,但是刚开始没读清题,wa了一发,之后又少考虑了情况,又wa了一发。1007比较可惜,3点多就反应出来是二分图最小覆盖问题,结果没去找算法,而是想手写,没写出来。。前面我们一直采用简单题单开,然后中期两个人看一道,一个人去开另一道,一直到1005出来还算好,但是一个人单开1004却卡了很久,一直到最后一个小时的时候还是两个人看1007一个人看1004,结果导致最后发现1007方法错误想要去做1004的时候已经没时间看懂队友的代码。
总的来看感觉21分的效果还可以,但是还是感觉需要一个自由人,俩人各开一道题写,剩下一个两个都看,等俩人写完之后检查一下代码再交,应该对于wa的情况有所帮助。
题解
1002
题意
俩人对枪,有多把枪可选,每把枪都有伤害和装填时间两种属性,如果俩人同时死亡的话你有 50 % 50\% 50% 的几率取胜,问在对方随机选枪的情况下,你最大的获胜概率。
解法
水题,算一下最快打死对方的枪有几把,稍微计算一下就可以。
代码
#include
#define FOR(a,b,c) for(int a=b;a<=c;a++)
#define RFOR(a,b,c) for(int a=b;a>=c;a--)
#define IO ios::sync_with_stdio(false), cin.tie(0)
#define endl '\n'
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 2e5 + 5;
int main(){IO;int t;cin >> t;while(t--){int n;cin >> n;map<int, int> mp;int minn = inf;FOR(i,1,n){int x, y;cin >> x >> y;int tmp = (ceil(100.0 / x) - 1) * y;mp[tmp]++;minn = min(minn, tmp);}double ans = mp[minn] * 0.5 / n;printf("%.6f\n", 1 - ans);}return 0;
}
1004
题意
有n个点m条边的无向图,每条边有自己的长度(即通过时间)。每个点有不同的手势要求,切换手势要x的时间,求从起点到中终点的最短时间。
解法
比赛时第一个看的是这道题,分析了大概问题在于要拆点,就去做签到提了,当时只是觉得要把M点拆成一左一右两个点,后面看人家题解可以把每个点都拆成俩分别建边,空间复杂度居然吃的消,然后补题的时候因为存边的数组开小了(居然要乘8倍,而且开小了还T),然后还被strlen函数坑了一把,有一说一这玩意复杂度要是放在循环里可吃不消,这也是一个T的原因,总结来说这道题就是一个拆点+dijjiskra,但是边的空间大小这里比较坑。
代码
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <string>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <fstream>
#include <unordered_map>
using namespace std;
#define ms(a, x) memset(a, x, sizeof(a))
#define fore(i, a, n) for (ll ll i = a; i < n; i++)
#define ford(i, a, n) for (ll ll i = n - 1; i >= a; i--)
#define si(a) scanf("%d", &a)
#define sl(a) scanf("%lld", &a)
#define sii(a, b) scanf("%d%d", &a, &b)
#define siii(a, b, c) scanf("%d%d%d", &a, &b, &c)
#define sll(a, b) scanf("%lld%lld", &a, &b)
#define slll(a, b, c) scanf("%lld%lld%lld", &a, &b, &c)
#define ss(a) scanf("%s", a);
#define debug(a) cout << a << endl
#define pr(a) printf("%d ", a)
#define endl '\n'
#define pi acos(-1.0)
#define tr t[root]
#define IO ios::sync_with_stdio(false), cin.tie(0)
#define ull unsigned long long
#define py puts("Yes")
#define pn puts("No")
#define pY puts("YES")
#define pN puts("NO")
#define re(i, a, b) for (int i = a; i <= b; ++i)
#define de(i, a, b) for (int i = a; i >= b; --i)
#define all(x) (x).begin(), (x).end()
#define ls(x) x.resize(unique(all(x)) - x.begin())
const double eps = 1e-3;
inline int sgn(const double &x) { return x < -eps ? -1 : x > eps; }
typedef long long ll;
typedef pair<ll, int> pli;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const ll INF = 0x3f3f3f3f;
template <class T>
inline void cmin(T &a, T b) { ((a > b) && (a = b)); }
template <class T>
inline void cmax(T &a, T b) { ((a < b) && (a = b)); }
long long PRIMES[223] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409};
const int MAXN = 8e5 + 10;
const ll mode = 1e9 + 9;
ll Pow(ll a, ll b)
{ll sum = 1;a = a % mode;while (b > 0){if (b % 2 == 1) //判断是否是奇数,是奇数的话将多出来的数事先乘如sumsum = (sum * a) % mode;b >>= 1;a = (a * a) % mode; // 不断的两两合并再取模,减小a和b的规模}return sum;
}
//-----------------------------------------------------------------------------------------int n, m, s, t, xx;
long long d[MAXN];
int head[MAXN],ver[4 * MAXN],edge[4 * MAXN], Next[4 * MAXN];//开两倍存储双向边
bool v[MAXN];
int tot=0;
priority_queue<pair<long long,int> >q;//这里别忘long long
int hand[MAXN];
char S[100005];
void add(int x,int y,int z)
{ver[++tot]=y;edge[tot]=z;Next[tot]=head[x];head[x]=tot;
}
long long dijkstra(int s, int t)
{long long ans = 1e18;for(int i = 1; i <= 2 * n; i++) d[i] = 1e18;memset(v, 0, sizeof(v));d[s]=0;q.push(make_pair(0,s));int i,j;while(q.size()){int x=q.top().second;q.pop();if(v[x])continue;v[x]=1;for(i=head[x];i;i=Next[i]){int y=ver[i],z=edge[i];if(hand[x] != hand[y]) z += xx;//是否要换手 if(d[y]>d[x]+z){d[y]=d[x]+1ll * z;q.push(make_pair(-d[y],y));}}}return min(d[t], d[t + n]);
}signed main()
{int T;si(T);while (T--){siii(n,m,s);sii(t,xx);ss(S);tot = 0;re(i, 1, 2 * n) head[i] = 0;int l=strlen(S);for (int i = 0; i <l ; i++){if (S[i] == 'L'){hand[i + 1] = hand[i + 1 + n] = 0;}else if (S[i] == 'R'){hand[i + 1] = hand[i + 1 + n] = 1;}else{hand[i + 1] = 0;hand[i + 1 + n] = 1;}}re(i, 1, m){int u, v, w;siii(u, v, w);add(u, v, w);add(v, u, w);add(u + n, v, w);add(v, u + n, w);add(u, v + n, w);add(v + n, u, w);add(u + n, v + n, w);add(v + n, u + n, w);}ll ans = min(dijkstra(s,t), dijkstra(s + n,t));printf("%lld\n", ans);}return 0;
}
1005
题意
有俩字符串 a , b a,b a,b,如果这两个字符串包含的字符种类数量一样,且所有字符 x x x 在 a , b a,b a,b 中的第 i i i 次出现的位置相差不超过 1,则说明这俩字符串大致相等,问你有多少和给出的字符串大致相等的字符串(包含自己)。
解法
算是个简单题把,易得其实就是让你交换相邻的不同字符,注意一个字符只能换一次,也可以不换,只要你先把字符串分段,分界点是相同的字符,比如 a b c d d e f abcddef abcddef 需要分成 a b c d abcd abcd 和 d e f def def 两段,再把这两段的交换种类相乘即可。
发现长度为 l e n len len 的一段的交换种类其实只和 l e n len len 有关,所以要 DP 预处理, d p [ i ] dp[i] dp[i] 代表长度为 i i i 的段具有的交换种类,状态转移方程比较好想:
d p [ i ] = ( d p [ i − 1 ] + d p [ i − 2 ] + 1 ) % m o d dp[i]=(dp[i-1]+dp[i-2]+1)\%mod dp[i]=(dp[i−1]+dp[i−2]+1)%mod 其中 d p [ i − 1 ] dp[i-1] dp[i−1] 是如果第 i i i 位不参与交换的种类, d p [ i − 2 ] dp[i-2] dp[i−2] 是 i i i 和 i − 1 i-1 i−1 位交换的种类,最后还要加上只有 i i i 和 i − 1 i-1 i−1 位交换的种类,也就是 1,举个 n = 5 n=5 n=5 的例子就明白了。
代码
#include
#define FOR(a,b,c) for(int a=b;a<=c;a++)
#define RFOR(a,b,c) for(int a=b;a>=c;a--)
#define IO ios::sync_with_stdio(false), cin.tie(0)
#define ll long long
#define endl '\n'
using namespace std;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const int maxn = 2e5 + 5;
vector<int> v;
map<string, int> mp;
ll cal[maxn];
int main(){IO;int t;cin >> t;cal[1] = 0; cal[2] = 1;FOR(i,3,maxn-1){cal[i] = (cal[i - 1] + cal[i - 2] + 1) % mod;}while(t--){int n;cin >> n;v.clear(), mp.clear();int cnt = 0;FOR(i,1,n){string s;cin >> s;if(!mp[s]){mp[s] = ++cnt;v.push_back(cnt);}else v.push_back(mp[s]);}int m = v.size();int f = 0;ll ans = 1;int len = 1;vector<int> duan;FOR(i,1,m-1){if(v[i]!=v[i-1]){len++;f = 1;}if(v[i]==v[i-1]||i==m-1){if(f){duan.push_back(len);len = 1;f = 0;}}}for(auto i:duan){ans = ans * (cal[i] + 1) % mod;}cout << ans << endl;}return 0;
}
1007
题意
翻译过来就是:给你几对数,假如是 x , y x,y x,y,这一对数可以选择归属 x + y x+y x+y组,或选择归属 x − y x-y x−y组,没有该组就创建一个组,问你怎么选择归属才能让组数最少。
解法
其实你可以把每一对数的 x + y x+y x+y 和 x − y x-y x−y 都算出来,分别离散化一下,之后把 x + y x+y x+y 放左边, x − y x-y x−y 放右边,中间根据输出的 n n n 个数据连 n n n 条边,然后问题就转换成了二分图最小点覆盖问题,有一个结论为:二分图的最小点覆盖等于二分图的最大匹配。所以求出这个二分图的最大匹配即可。感觉建图比较巧,但是仔细想想也挺有道理。
代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define ull unsigned long long
#define IO ios::sync_with_stdio(false), cin.tie(0)
#define endl '\n'
#define pi acos(-1)
#define lowbit(x) ((x)&(-(x)))
#define debug(x) cout<
#define FOR(a,b,c) for(int a=b;a<=c;a++)
#define RFOR(a,b,c) for(int a=b;a>=c;a--)
#define debug(x) cout<
#define all(x) (x).begin(), (x).end()
#define ls(x) x.resize(unique(all(x)) - x.begin())
using namespace std;
typedef pair<int,int> P;
typedef pair<double,double> Pd;
const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, 1, 0, -1};
const ll INF=0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const ll mod = 1e9+7;
const double eps = 1e-11;
ll gcd(ll a, ll b) {return b==0?a:gcd(b, a%b);}
ll lcm(ll a, ll b) {return a/gcd(a, b)*b;}
ll mul(ll a,ll b){ll ans=0;a%=mod,b%=mod;while(b) { if(b&1) ans = (ans+a)%mod; a = (a*2)%mod; b >>= 1; }return ans;}
ll powmod(ll a,ll b){ll ans = 1;a %= mod;b%=(mod-1);while(b){if(b & 1){ans = ans * a % mod;b--;}b >>= 1;a = a * a % mod;}return ans;}
//(b/a)%p=b*a^(p-2)%p
int pr(ll num){if(num == 1) return 0;if(num ==2|| num==3 ) return 1 ;if(num %6!= 1&&num %6!= 5) return 0 ;int tmp =sqrt( num);for(int i= 5;i <=tmp; i+=6 )if(num %i== 0||num %(i+ 2)==0 )return 0 ;return 1 ;}
int Day(int y,int m, int d){if(m==1||m==2) { m+=12; y--; }int w=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7;return w+1;}
ll C(ll n,ll m) {if(n < m) return 0;ll res = 1;for(int i=1; i<=m; i++) {ll a = (n+i-m)%mod;ll b = i%mod;res = res*(a*powmod(b,mod-2)%mod)%mod;}return res;}
ll Lucas(ll n,ll m) {if(m == 0) return 1;return C(n % mod, m % mod) * Lucas(n / mod, m / mod) % mod;}
//long long PRIMES[223] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409};
//const int maxn=2e7+5;
//ll v[maxn] = {0}, prime[maxn], Cnt = 0;
//void getpri(ll n) {for (ll i = 2; i <= n; ++i) {if (!v[i]) { v[i] = i; prime[++Cnt] = i;}for (ll j = 1; j <= Cnt; ++j) {if (prime[j] > v[i] || prime[j] * i > n) break; v[i * prime[j]] = prime[j];}}}
const int maxn=2e5+15;
struct ac{int x, y;
} a[maxn];
int cnt;
int n, m, s, t;
bool vis[maxn];
ll d[maxn], cur[maxn];
struct Edge {int u, v;ll cap, flow;
} e[maxn*6];
vector<ll> G[maxn];
void init(int n) {cnt = 0;for (int i = 0 ; i <= n ; i ++) G[i].clear();
}
void add(int u, int v, ll cap, ll f) {e[cnt] = Edge{u, v, cap, f};
}
void AddEdge(int u, int v, ll cap) {add(u, v, cap, 0);G[u].push_back(cnt++);add(v, u, 0, 0);G[v].push_back(cnt++);
}
bool BFS() {fill(vis, vis + 2 * n + 6, 0);queue<ll> q; q.push(s);vis[s] = 1; d[s] = 0;while (!q.empty()) {int v = q.front(); q.pop();for (int i = 0; i < G[v].size(); i++) {Edge &te = e[G[v][i]];if (!vis[te.v] && te.cap > te.flow) { vis[te.v] = 1;d[te.v] = d[v] + 1;q.push(te.v);}}}return vis[t];
}
ll dfs(int x, ll a) {if (x == t || a == 0) return a;ll flow = 0, f;for (ll &i = cur[x]; i < G[x].size(); i++) { Edge &te = e[G[x][i]];if (d[x] + 1 == d[te.v] && (f = dfs(te.v, min(a, te.cap - te.flow))) > 0) {te.flow += f;e[G[x][i]^1].flow -= f;flow += f;a -= f;if (a == 0) break;}}return flow;
}
ll Dinic() {ll flow = 0;while (BFS()) {fill(cur, cur + 2 * n + 6, 0);flow += dfs(s, inf);}return flow;
}int main(){IO;int T;cin >> T;while(T--){cin >> n;map<ll, int> ls1, ls2;vector<int> be, end;int cnt1 = 1, cnt2 = 1;FOR(i,1,n){int x, y;cin >> x >> y;a[i].x = x, a[i].y = y;if(!ls1[x+y]) ls1[x + y] = cnt1++, be.push_back(ls1[x + y]);if(!ls2[x-y]) ls2[x - y] = cnt2++, end.push_back(ls2[x - y]);}init(2 * n + 5);s = 0, t = 2 * n + 4;for(auto i:be){AddEdge(s, i, 1);}FOR(i,1,n){int u, v;u = ls1[a[i].x + a[i].y];v = ls2[a[i].x - a[i].y];AddEdge(u, v + n, 1);}for(auto i:end){AddEdge(i + n, t, 1);}ll ans = Dinic();cout << ans << endl;}return 0;
}
1011
题意
给你俩球的质量和初始距离 d d d,这俩球只受相互的万有引力,问你 t t t 时刻这俩球相聚多远, e p s = 1 e − 6 . eps=1e{-6}. eps=1e−6.
解法
很奇葩的一道题,我还以为是积分问题,后来看到 t t t 最大才是100,生活常识告诉我100秒内俩球相互吸引的距离可以忽略不计。保险点就输出 d − 0.000001 d-0.000001 d−0.000001,其实直接输出 d d d 就能过。
代码
#include
using namespace std;
#define FOR(a,b,c) for(int a=b;a<=c;a++)
#define RFOR(a,b,c) for(int a=b;a>=c;a--)
#define IO ios::sync_with_stdio(false), cin.tie(0)
#define endl '\n'
const int maxn = 2e5 + 5;
int main(){IO;int t;cin >> t;while(t--){double a, b, c, d;cin >> a >> b >> c >> d;printf("%.20f\n", c );}return 0;
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
