真题演练1
ACM-ICPC 2017 Asia Shenyan
F. Heron and His Triangle
三边长给出,海伦公式算出面积,暴力枚举整数情况,得:
4,14,52,194,724等数据
之后就要灵性找规律了,得:a[i] = a[i-1]*4-a[i-2]
总结:1.对于类似题目,暴力枚举出一大串数据之后,应该第一时间反应过来找规律。 2.大数题应考虑java或python写(java暂时不会)
a={} a[1]=4 a[2]=14 for i in range(3,61,1): a[i]=a[i-1]*4-a[i-2] t=int(input()) for i in range(1,t+1,1): k=int(input()) for j in range(1,61,1): if a[j]>=k : print(a[j]) print("\n") break
G. Infinite Fraction Path
bfs+剪枝即可
总结:对于普通情况而言,一个不起眼的剪枝根本起不到作用,但是对于十分极端情况而言,比如数据全都是同一个数,这个剪枝算是能够“特判”掉这种数据,避免超时。
#include <bits/stdc++.h> #define debug freopen("r.txt","r",stdin) #define mp make_pair using namespace std; typedef long long ll; const int maxn = 250010; const int INF = 0x3f3f3f3f; const int mod = 998244353; inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} struct node { int step; ll pos; }; int b[maxn],vis[maxn],c[maxn],i,j,t,maxx,cnt,x; ll n; char ans[maxn],s[maxn],a[maxn]; queue<node> q; map <int,int> mapp; void bfs() { node k; while (!q.empty()) { k=q.front(); q.pop(); if (k.step==n) continue; if (s[k.pos]==ans[k.step]) { if (vis[k.pos]==k.step) continue;//important vis[k.pos]=k.step; k.pos=(k.pos*k.pos+1)%n; k.step++; if (s[k.pos]>=ans[k.step]) { ans[k.step]=s[k.pos]; q.push(k); } } } } int main() { t=read(); while (t--) { n=read(); scanf("%s",s); maxx=-INF; memset(ans,-1,sizeof(ans)); while (!q.empty()) q.pop(); for (i=0;i<n;i++) { maxx=max(maxx,(int)s[i]); } for (i=0;i<n;i++) if (maxx==s[i]) { q.push({1,i}); } memset(vis,-1,sizeof(vis)); ans[1]=maxx; bfs(); printf("Case #%d: ",++cnt); ans[n+1]='\0'; printf("%s",ans+1); printf("\n"); } return 0; }
I. Little Boxes
如果直接四个数相加,数据可能会刚好等于2^64次方,超过ull,这时候可以特判,也可以python做
总结:对于一道真的裸的不能再裸的签到题,写完应该看一眼提交榜单,或许有其他倒霉蛋踩了坑,提交上去怒收WA,这时候应该注意此题有坑。
K. Rabbits
普通签到题,没有I题裸
#include <bits/stdc++.h> #define debug freopen("r.txt","r",stdin) #define mp make_pair using namespace std; typedef long long ll; const int maxn = 150005; const int INF = 0x3f3f3f3f; const int mod = 998244353; inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} int t,n,i,sum,a[maxn]; int main() { t=read(); while (t--) { n=read(); sum=0; for (i=1;i<=n;i++) a[i]=read(); if (a[2]-a[1]<a[n]-a[n-1]) for (i=2;i<n;i++) sum+=a[i+1]-a[i]-1; else for (i=1;i<n-1;i++) sum+=a[i+1]-a[i]-1; cout<<sum<<endl; } return 0; }
L. Tree
题意:给了一个无向图,题目保证了是连通图,可以看成一棵树。然后给N个结点分别涂上K种颜色,所有相同颜色的结点连在一起构成一个边集,问所有边集的交集最大是多少?
可以对边进行考虑,边连结两侧,那么只有当两侧的结点数量>=k时才可能满足该边是所有边集的公共边。统计一下满足这种条件这种公共边的数量就是答案了。
#include <bits/stdc++.h> #define debug freopen("r.txt","r",stdin) #define mp make_pair using namespace std; typedef long long ll; const int maxn = 250010; const int INF = 0x3f3f3f3f; const int mod = 998244353; inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} int t,n,m,i,x,y,ans,son[maxn]; vector <int> G[maxn]; void dfs(int u,int father) { son[u]+=1; for (auto v:G[u]) { if (v==father) continue; dfs(v,u); son[u]+=son[v]; if (son[v]>=m&&n-son[v]>=m) ans++; } } int main() { t=read(); while (t--) { n=read(),m=read(); fill(son+1,son+1+n,0); for (i=1;i<n;i++) { x=read(),y=read(); G[x].push_back(y); G[y].push_back(x); } ans=0; dfs(1,0); cout<<ans<<endl; for (i=1;i<=n;i++) G[i].clear(); } return 0; }
总结:这种题目偏长,题意也难懂但是解法相对简单的题目,需要比较深的英语、语文功底才能做的了,但是这种题目如果率先读完了解题意并且AC,或许是与别人拉开差距的题目。