天梯赛2020题解_最强大脑第十一季速算赛道

(4) 2024-10-07 12:01:01

较简单的题直接上代码不多解释

7-1 日期格式化 (5 分)

#include<bits/stdc++.h> using namespace std; int main() { string s; cin>>s; for(int i=6;i<10;i++) cout<<s[i]; cout<<'-'; for(int i=0;i<=4;i++) cout<<s[i]; } 

7-2 求整数段和 (10 分)

这道题看有同学说总是格式错误,我在下面标注了格式的坑。

#include<bits/stdc++.h> using namespace std; int main() { int a,b; cin>>a>>b; int cnt=0; int sum=0; for(int i=a;i<=b;i++) { printf("%5d",i); cnt++; sum+=i; if(cnt%5==0) printf("\n"); } if((b-a+1)%5!=0)printf("\n");//坑点在这 cout<<"Sum = "<<sum; }

7-3 洛希极限 (10 分)

这道题看很多人说卡了很久,其实我觉得前面一大堆看起来很高大上的东西好像并不需要理解也可以做这道题,就是简单套公式,比如他给的例子0.622×2.455=1.52701,然后判断输入的第三个数是否小于这个就可以了。

#include<bits/stdc++.h> using namespace std; int main() { double a,b,c; scanf("%lf%lf%lf",&a,&b,&c); if(b==0) b=2.455; if(b==1) b=1.26; double k=a*b; printf("%.2f ",k); if(c-k>=0.00001) printf("^_^"); else printf("T_T"); } 

7-4 幸运彩票 (15 分)

#include<bits/stdc++.h> using namespace std; int main() { int t; cin>>t; while(t--) { char s[6]; cin>>s; int sum1=0,sum2=0; for(int i=0;i<3;i++) { sum1+=(int)(s[i]-'0'); } for(int i=3;i<6;i++) { sum2+=(int)(s[i]-'0'); } if(sum1==sum2) printf("You are lucky!\n"); else printf("Wish you good luck.\n"); } }

7-5 个位数统计 (15 分)

#include<bits/stdc++.h> using namespace std; int a[10]; int main() { string s; cin>>s; int len=s.length(); for(int i=0;i<len;i++) a[s[i]-'0']++; for(int i=0;i<=9;i++) { if(a[i]!=0) cout<<i<<":"<<a[i]<<endl; } }

7-6 考试座位号 (15 分)

#include<bits/stdc++.h> using namespace std; struct node { string ID; int sj,ks; }stu[1001]; int a[1001]; bool cmp(node a,node b) { return a.sj<b.sj; } int main() { int n; cin>>n; for(int i=1;i<=n;i++) cin>>stu[i].ID>>stu[i].sj>>stu[i].ks; sort(stu+1,stu+1+n,cmp); int m; cin>>m; for(int i=0;i<m;i++) { cin>>a[i]; } for(int i=0;i<m;i++) { cout<<stu[a[i]].ID<<' '<<stu[a[i]].ks<<endl; } }

7-7 连续因子 (20 分)

这道是我个人认为这次题里面比较难的,也是卡挺久的题。

一开始看到数据范围10的九次方好像不太能暴力,就写了个这样的代码

12的阶乘就超了他给的数据范围,所以我就把阶乘限制到12,也就是我认为最长连续因子段中的每个数都小于12,然后get2是计算 i 到 j 区间元素的积,然后枚举这些区间,如果这些区间的积能被n整除就说明他是它的一个连续因子段,然后更新最大值就可以了。

#include<bits/stdc++.h> using namespace std; int a[14]; int b[14][14]; void get1()//计算阶乘 { a[0]=1; for(int i=1;i<=13;i++) a[i]=i*a[i-1]; } void get2()//计算各子段 { for(int len=0;len<=13;len++) { for(int i=2;i+len<=13;i++) { int j=i+len; b[i][j]=a[j]/a[i-1]; } } } int main() { get1(); get2(); long long n; scanf("%d",&n); int maxn=0; int ansi,ansj; for(int i=2;i<=13;i++) { for(int j=i;j<=13;j++) { if(n>=b[i][j]&&n%b[i][j]==0) { int len=j-i+1; if(len>maxn) { maxn=len; ansi=i; ansj=j; } } } } if(maxn==0) { cout<<1<<endl<<n<<endl; return 0; } printf("%d\n",maxn); for(int i=ansi;i<=ansj-1;i++) cout<<i<<"*"; cout<<ansj<<endl; }

这个代码交上去居然有19分,也就是只错了一个样例,我当时还以为是哪里出了点小错调半天,最后发现,比如17*18*19=5814,这个跑出来结果是2   2*3,所以我就发现这代码从一开始就错了(如果是正式比赛这一分我肯定不纠结了)。

接下来是ac代码:

其实这道题是可以暴力的,1e9的范围开个方就只剩1e5,然后再用我们上面的结论,就是最多给他阶乘到12,所以就10*1e5的复杂度,这肯定不会超时。

思路:最长因子段的第一个元素最多到sqrt(n),不然最长长度也超不过1,所以我们枚举因字段的开头,然后用一个while循环让这个开头元素一直加一,判断能不能继续被整除,可以就往下长度加一,最后更新最大值就可以了。

一开始交上去居然只有18分,然后我发现了天梯赛2020题解_最强大脑第十一季速算赛道 (https://mushiming.com/)  第1张

 怎么这两个错误答案的时间比别的长那么多,再看看我代码len==1的情况里用了cout<<endl;

这个好像比printf("\n")慢很多,然后就可以快速锁定应该是这地方出题,然后又过了很久才发现其实因子好像不能是本身,随后ac了。

7-8 N个数求和 (20 分)

这道题就是模拟一下最常规的分数相加流程了:通分-->分子相加

这里通分要找公倍数,介绍求公倍数的方法:a,b的公倍数就是a*b/gcd(a,b)

#include<bits/stdc++.h> using namespace std; #define ll long long ll a[101],b[101]; ll gcd(ll x,ll y) { if(y==0) return x; else return gcd(y,x%y); } ll lcm(ll x,ll y) { ll k=x*y; ll _=gcd(x,y); return k/_; } int main() { int n; scanf("%d",&n); ll fm=1; for(int i=0;i<n;i++) { scanf("%lld/%lld",&a[i],&b[i]); } for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { ll k=lcm(b[i],b[j]); if(k>fm) { fm=k; } } } ll fz=0; for(int i=0;i<n;i++) { ll k=fm/b[i]; a[i]*=k; fz+=a[i]; } ll k=gcd(fz,fm); fz/=k; fm/=k; if(fz==0) { cout<<0; return 0; } int t1=0,t2=0; if(fz/fm) { printf("%lld",fz/fm); t1=1; } if(fz%fm) t2=1; if(t1==1&&t2==1) printf(" "); if(fz%fm) { printf("%lld/%lld",fz%fm,fm); } } 

7-9 帅到没朋友 (20 分)

#include<bits/stdc++.h> using namespace std; int vis[]; bool check[]; int cha[10000]; int cun[10000]; int main() { int N; scanf("%d",&N); while(N--) { int x; scanf("%d",&x); for(int i=0;i<x;i++) { int k; scanf("%d",&k); vis[k]=1; } } int t=0; int M; scanf("%d",&M); for(int i=0;i<M;i++) cin>>cha[i]; int cnt=0; for(int i=0;i<M;i++) { if(check[cha[i]]==0&&vis[cha[i]]==0) { cun[++cnt]=cha[i]; vis[cha[i]]=1; } } if(cnt==0) printf("No one is handsome"); else{ for(int i=1;i<=cnt;i++) { char s[5]; s[0]=(char)(cun[i]/10000+'0'); s[1]=(char)(cun[i]/1000%10+'0'); s[2]=(char)(cun[i]/100%10+'0'); s[3]=(char)(cun[i]/10%10+'0'); s[4]=(char)(cun[i]%10+'0'); for(int j=0;j<=4;j++) printf("%c",s[j]); if(i!=cnt) printf(" "); } } } 

这道题一直ac不了,调的过程中发现了1个错误的地方:首先是ID一定是5位,比如00100也要输出00100,如果简单用数组存会输出100。

然后还有打天梯赛训练一直有的奇葩要求,输出首尾不能又多余的空格。

7-10 天梯赛的善良 (20 分)

这个数据范围完全可以只用数组来存,属于是比较笨的方法了。

#include<bits/stdc++.h> using namespace std; int a[]; int main() { int n; scanf("%d",&n); for(int i=0;i<n;i++) { int x; scanf("%d",&x); a[x]++; } for(int i=0;i<=;i++) { if(a[i]) { printf("%d %d\n",i,a[i]); break; } } for(int i=;i>=0;i--) { if(a[i]) { printf("%d %d",i,a[i]); break; } } }

第一次写题解,写得不好的地方多多包涵。

THE END

发表回复