第一次参赛,很不错的体验
因为疫情的原因,不能线下打了qwq,不过体验还是很不错的
早上7点多起,吃个面包,8点到场,然后就看看腾讯会议上其他学校的队伍发呆,看看队友玩原神,把屏幕录制开起来 ,屏幕录制是2帧的,可以 帧 间 作 弊( 误 )
比赛时同时只能使用一个IDE(不知道为什么),不过我们也只用得到Dev 。
字典的话,我们三人都没,就没带233 ,不过影响也不大,都是靠的样例推的题目意思(
打印机我们比赛时也没用到 。
9点了,我们一开始的分配是一个队友开前4题,另一个队友开中4题,我开后4题,我们先是都看了下H题,然后一个队友开始看A,我和另一个队友看H 。
刚开始的时候,好多人交A题,全wa了,然后我们队看样例过了也莽交了一发wa了,我们就一起分析,然后我看样例察觉到2n个人都过桥后,工具人是留在左端的,
于是就变成了一个 先走 还是 先等2号后走 的问题,这个问题我们还分析了挺久,代码写的也很复杂,用了三目运算符,交的时候有种很可能wa的感觉,还好过了 。
42min时过了,比赛时的AC代码:
#include <bits/stdc++.h> using namespace std; #define endl " " //const int MAXN = ; //const int INF = 0x3f3f3f3f; int T; long long n, x, t; unsigned long long ans; int main(void) { // 1000000000 ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> T; while (T--) { ans = 0; cin >> n >> x >> t; ans += 2 * n * t; if ((2 * n - 2) * t >= x) { ans *= 2; } else { ans += (x - (2 * n - 2) * t) > t ? (t > (x - (2 * n - 1) * t) ? t : (x - (2 * n - 1) * t)) : (x - (2 * n - 2) * t); ans += 2 * n * t; } cout << ans << endl; } return 0; }
然后我们就研究H题了,容易想到是一个差分,但是数组难开,为了减少空间,要开vector,然后自己在草稿纸上开了好多数组,关系很复杂,队友1过A后,我开始写H,写的时候卡壳了,数组又开不来了,
又开始重新构思,后来二分查找又写不来了。。我连二分查找都写不来了,还得请队友帮忙,后来跟队友讲了我的做法后,他提出了一种O(1)处理的办法,就不用二分了,感谢队友的指点,提供了很大的帮助,不过我还是写的很丑陋就是了。。队友:你怎么写的那么复杂
写了差不多1小时? 1时48min时才过,一遍过的
来欣赏下我丑陋无比的代码(
#include <bits/stdc++.h> using namespace std; #define endl " " const int MAXN = 2e5 + 7; //const int INF = 0x3f3f3f3f; int n, m, s; int t, x, y; vector<int> su[MAXN]; vector<int> id[MAXN],fid[MAXN]; vector<pair<int ,int > >nbr[MAXN]; int fa[MAXN]; bool vis[MAXN]; int dd[MAXN]; int ans[MAXN]; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> m >> s; for( int i = 1;i<=s;i++) { cin >> t >> x >> y; if(t == 1){ nbr[x].push_back(make_pair(y,su[y].size())); id[x].push_back(y); } if(t == 2){ nbr[x].push_back(make_pair(y,su[y].size())); id[x].push_back(y); } if(t == 3) { fa[x]++; su[y].push_back(i); } } for(int i = 1;i<=m;i++){ for(int j = 0;j < id[i].size();j++){ vis[id[i][j]] = false; } for(int j = 0;j < nbr[i].size();j++ ){ int gu = nbr[i][j].first; int sjs = nbr[i][j].second; if(!vis[gu]) { dd[gu] = sjs; vis[gu] = true; } else{ vis[gu] = false; ans[i] += sjs - dd[gu]; } } for(int j = 0 ;j<id[i].size();j++){ int gu = id[i][j]; if(vis[gu]){ vis[gu] = false; ans[i] += su[gu].size() - dd[gu]; } } ans[i] -=fa[i]; } for(int i = 1;i<=m;i++){ cout<<ans[i]<<endl; } return 0; }
然后我就看D题了,这时队友开了D和L这两个和质数有关的题
D题和队友研究出来是判断c是否能被一个质数的平方整除,c是大到1e18的,我的第一反应就是筛1e9的素数,而且还是用欧拉筛,我当时真的以为能在时间范围内筛出来
既然筛1e9不行,那就筛小一点,然后我就干脆不筛了,就直接暴力
for(int i = 2;i<=1e8;i++){ if(c%(i*i) == 0) { flag = true; break; } if(c%i==0) c/=i; }
也就是只要c不够大的情况下,我是能判断出来yes还是no的,至于c足够大的情况下,我就当它是no 2333
样例肯定能过,然后就交上去了,TLE了,于是我就把那个1e8改小点,还是T了,再改小,改到不T为只,果然wa了233
然后我就在这个地方思考,突然想到一个点,跟队友解释了一下,我暴力过滤掉小于1e6的素数后,最多只剩下两个素数了,我们就判断这两个素数是否相同即可
我把最初的1e8改成2e6,再求个sqrt再平方来判断,就过了
AC的那一刻队友真的特别激动,都跳起来了,队友本来想用大数素数分解的板子,但我们没带这个板子,我都不知道有这个板子 。
因为是打星参赛,所以交的很莽
2时29min时过
#include<iostream> #include<algorithm> #include<cmath> using namespace std; int main() { int T; long long c; cin>>T; while(T--){ cin>>c; bool flag = false; int cnt = 0; for(long long i = 2;i*i<=c&&i<=(long long)2e6;i++){ if(c%(i*i)==0) { flag = true; break; } if(c%i==0){ c/=i; cnt++; } } if(flag) cout<<"yes "; else if(c>1){ long long zs = sqrt(c); if(zs*zs==c) cout<<"yes "; else cout<<"no "; } else cout<<"no "; } return 0; }
之后就看另一道素数题,L题了
这题范围就小多了,我研究了下,感觉很有背包的意思,就分析出来是分组背包了,
这时候午饭来了,我和一位队友开始吃午饭,另一位队友写分组背包,午饭的菜还挺好吃的,鱼有点辣好吃,还有苹果和酸奶 。
吃完午饭后就开始帮队友调分组背包了,样例过了之后,PE了一发 ?又wa了一发,一开始dp数组是开int的,然后改成long long,发现long long也会爆,
应该要及时取对数,然后我们再转移方程里取对数,就T了,最后把物品的价值去对数,就过了
3时22min时过的
#include <bits/stdc++.h> using namespace std; #define endl " " const int MAXN = 3e4 + 7; //const int INF = 0x3f3f3f3f; int n; int cnt; vector<pair<int ,long double> > prime[MAXN]; bool vis[MAXN]; long double dp[30007]; void GetPrime() { memset(vis, false, sizeof(vis)); cnt = 0; for (int i = 2; i < MAXN; ++i) { if (!vis[i]) prime[++cnt].push_back(make_pair(i,log(i))); for (int j = 1; j <= cnt && i <= MAXN / prime[j][0].first; ++j) { vis[i * prime[j][0].first] = true; if (i % prime[j][0].first == 0) break; } } //cout << cnt << endl; } void init() { for (int i = 1; i <= cnt; ++i) { int nxt = prime[i][0].first * prime[i][prime[i].size() - 1].first; while (nxt < 3e4 + 7) { prime[i].push_back(make_pair(nxt,log(nxt))); nxt *= prime[i][0].first; } } } void solve() { dp[0] = 0; for (int i = 1; i <= 30000; ++i) dp[i] = 0; for (int i = 1; i <= cnt; ++i) { for (int v = 30005; v; --v) { for (int j = 0; j < prime[i].size(); ++j) { if (v >= prime[i][j].first) dp[v] = max(dp[v], dp[v - prime[i][j].first] + prime[i][j].second); } dp[v] = max(dp[v], dp[v - 1]); } } } int main(void) { // ios::sync_with_stdio(false); // cin.tie(0); cout.tie(0); GetPrime(); init(); solve(); int T; cin>>T; while(T--) { cin >> n; //cout << dp[n] << endl; printf("%.9Lf", (long double)dp[n]); if (T > 0) printf(" "); } return 0; }
过完L题,就把两道素数题解决了,这时候放松下来边吃苹果边看C题,是一道树的题+概率的题,感觉挺难的,一开始我还想着怎么选目的顶点,一直没想出什么,
然后队友提出了边的贡献的想法,我们研究了下每一条边的贡献是怎么算的,我一下知道怎么写了,不过写的时候还是队友提供了很多帮助,wa了两发,int改long long,long long 还是被爆了,要提前除分母 。
4时35min时过的
#include<iostream> #include<algorithm> using namespace std; const int MAXN = 2e5+7; struct EDGE{ int to,next; long long w; }edge[MAXN*2]; int tot,head[MAXN]; void add(int u,int v,long long w){ tot++; edge[tot].to = v; edge[tot].w = w; edge[tot].next = head[u]; head[u] = tot; } long long fm = 1; long long siz[4][MAXN]; void dfs(int st,int f){ for(int i = head[st];i;i=edge[i].next){ int po = edge[i].to; if(po == f) continue; dfs(po,st); for(int t = 1;t<=3;t++) siz[t][st] += siz[t][po]; } } long double dfs2(int st,int f){ long double res = 0; for(int i = head[st];i;i = edge[i].next){ int po = edge[i].to; if(po == f) continue; long long w = edge[i].w; res += ((long double)siz[1][po] * (siz[2][1] - siz[2][po]) * (siz[3][1] - siz[3][po]) +(long double)siz[2][po] * (siz[1][1] - siz[1][po]) * (siz[3][1] - siz[3][po]) +(long double)siz[3][po] * (siz[1][1] - siz[1][po]) * (siz[2][1] - siz[2][po]) +(long double)siz[1][po] * siz[2][po] * (siz[3][1] - siz[3][po]) +(long double)siz[1][po] * siz[3][po] * (siz[2][1] - siz[2][po]) +(long double)siz[2][po] * siz[3][po] * (siz[1][1] - siz[1][po]) ) / (long double)fm * w; res+=dfs2(po,st); } return res; } int main() { int n; cin>>n; int u,v; long long w; for(int i = 1; i <= n-1; i++){ scanf("%d%d%lld",&u,&v,&w); add(u,v,w); add(v,u,w); } long long k; for(int i = 1; i <= 3; i++){ cin>>k; fm*=k; int tt; for(int j = 1;j <= k; j++) { scanf("%d",&tt); siz[i][tt]++; } } dfs(1,-1); long double fz = dfs2(1,-1); //long double ans = (long double)fz / (long double) fm; //cout<<fz<<endl<<fm<<endl; printf("%.12Lf ",fz); return 0; }
跟榜开的题,这次榜没歪,打的很好
完全看完的题有5题,过了5题,第1、2、3、4、5小时各一题
打的很不错,H题之后发挥的很好
唯一不足的就是罚时太高了,我们队5题罚时第二高,做的太慢了,也太莽了 。排在我们下面一名的那队是5题罚时第一高,A题9次提交,H题11次提交。。。。
纪念第一次参赛,小小甜心牛逼!