当前位置:   article > 正文

2023年中国高校计算机大赛-团队程序设计天梯赛(GPLT)上海理工大学校内选拔赛 题解_中国计算机天梯赛考试内容是什么

中国计算机天梯赛考试内容是什么

总结:本场比赛总共A了两题,主要是因为是在课上做的,老师一直比比个不停,还让关上手机电脑,静不下心去做,做题感觉很差

A A Xor B Problem

两个数异或和为零则两个数相等!!!

思路:使用数组记录每个数的个数,可以先输入,然后再对数组进行逐个遍历,可通过计算得出数对个数等于每个数的平方和。也可以边输入边处理,每输入一个数便更新数对的结果数

赛场AC代码:

  1. #include<cstdio>
  2. #include<iostream>
  3. #define int long long
  4. using namespace std;
  5. int a[100005];
  6. int b[114520];
  7. signed main(){
  8. int n,ans=0;
  9. cin>>n;
  10. for(int i=1;i<=n;i++){
  11. cin>>a[i];
  12. ans-=(b[a[i]]*b[a[i]]);
  13. b[a[i]]++;
  14. ans+=(b[a[i]]*b[a[i]]);
  15. }
  16. cout<<ans;
  17. return 0;
  18. }

另一种思路:

  1. #include<iostream>
  2. #define int long long
  3. using namespace std;
  4. const int N=1000005;
  5. int a[N];
  6. signed main(){
  7. int x,n,ans;
  8. cin>>n;
  9. for(int i=0;i<n;i++){
  10. cin>>x;
  11. a[x]++;
  12. }
  13. for(int i=0;i<=N;i++){
  14. ans+=a[i]*a[i];
  15. }
  16. cout<<ans;
  17. }

B 吃苹果 

思路:贪心算法,计算早上和晚上愉悦值的差并进行排序,差值越小(可能为负值)则代表晚上的愉悦值相对早上的更多,先选晚上的,剩下的则为早上的

注意对结构体的定义和结构体的排序!!!

赛场AC代码:

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<algorithm>
  4. #define int long long
  5. using namespace std;
  6. const int N=100005;
  7. struct Node{
  8. int a;
  9. int b;
  10. int c;
  11. }ap[N];
  12. bool cmp(Node x,Node y){
  13. return x.c<y.c;
  14. }
  15. signed main(){
  16. int n,k,ans=0;
  17. cin>>n>>k;
  18. for(int i=0;i<n;i++){
  19. cin>>ap[i].a>>ap[i].b;
  20. ap[i].c=ap[i].a-ap[i].b;
  21. }
  22. sort(ap,ap+n,cmp);
  23. for(int i=0;i<k;i++){
  24. ans+=ap[i].b;
  25. }
  26. for(int i=k;i<n;i++){
  27. ans+=ap[i].a;
  28. }
  29. cout<<ans;
  30. return 0;
  31. }

另一种思路:(也可以反过来)

  1. #include<iostream>
  2. #include<algorithm>
  3. using namespace std;
  4. const int N=100005;
  5. int a[N];
  6. int main(){
  7. int n,k,x,y;
  8. cin>>n>>k;
  9. int ans=0;
  10. for(int i=1;i<=n;i++){
  11. cin>>x>>y;
  12. ans+=x;
  13. a[i]=y-x;
  14. }
  15. sort(a+1,a+n+1,greater<int>());
  16. for(int i=1;i<=k;i++){
  17. ans+=a[i];
  18. }
  19. cout<<ans;
  20. }
  1. #include<iostream>
  2. #include<algorithm>
  3. using namespace std;
  4. const int N=100005;
  5. int a[N];
  6. int main(){
  7. int n,k,x,y;
  8. cin>>n>>k;
  9. int ans=0;
  10. for(int i=0;i<n;i++){
  11. cin>>x>>y;
  12. ans+=x;
  13. a[i]=x-y;;
  14. }
  15. sort(a,a+n);
  16. for(int i=0;i<k;i++){
  17. ans-=a[i];
  18. }
  19. cout<<ans;
  20. return 0;
  21. }

 C n皇后问题

 思路:用四个数组分别表示横竖左斜右斜

注意超时问题!!!

cin/cout会超时,需要用:   

ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

或者使用scanf!!!

  1. #include<iostream>
  2. #include<cstdio>
  3. using namespace std;
  4. const int N=3000005;
  5. bool h[N],l[N],a[N],b[N];
  6. int main(){
  7. ios::sync_with_stdio(false);
  8. cin.tie(0);
  9. cout.tie(0);
  10. int n,T;
  11. cin>>n>>T;
  12. while(T--){
  13. int x,y;
  14. cin>>x>>y;
  15. if(h[x]||l[y]||a[x-y+1000000]||b[x+y]){
  16. cout<<"No"<<endl;
  17. }else{
  18. cout<<"Yes"<<endl;
  19. h[x]=1;
  20. l[y]=1;
  21. a[x-y+1000000]=1;
  22. b[x+y]=1;
  23. }
  24. }
  25. return 0;
  26. }

D 分苹果 

思路:数学知识,将坐标分别带入直线方程,结果大于零和小于零位于直线两侧

  1. #include<iostream>
  2. #include<algorithm>
  3. #define int long long
  4. using namespace std;
  5. int ans[5];
  6. signed main(){
  7. int n,ae,be,ce,ar,br,cr;
  8. cin>>n;
  9. cin>>ae>>be>>ce;
  10. cin>>ar>>br>>cr;
  11. int x,y,a,b;
  12. while(n--){
  13. cin>>x>>y;
  14. a=ae*x+be*y+ce;
  15. b=ar*x+br*y+cr;
  16. if(a>0&&b>0){
  17. ans[0]++;
  18. }else if(a>0&&b<0){
  19. ans[1]++;
  20. }else if(a<0&&b>0){
  21. ans[2]++;
  22. }else{
  23. ans[3]++;
  24. }
  25. }
  26. sort(ans,ans+4);
  27. for(int i=0;i<4;i++){
  28. cout<<ans[i]<<' ';
  29. }
  30. return 0;
  31. }

E 完型填空

思路:动态规划,用数组dp[i][j][k][p]分别表示有ijkp道题选ABCD

  1. #include<iostream>
  2. using namespace std;
  3. const int N=30;
  4. int dp[N][N][N][N];
  5. int a[105][5];
  6. int main(){
  7. int n,h;
  8. cin>>n;
  9. for(int i=1;i<=n;i++){
  10. for(int j=1;j<=4;j++){
  11. cin>>a[i][j];
  12. }
  13. }
  14. for(int i=0;i<=n/4;i++){
  15. for(int j=0;j<=n/4;j++){
  16. for(int k=0;k<=n/4;k++){
  17. for(int p=0;p<=n/4;p++){
  18. h=i+j+k+p;
  19. if(i){
  20. dp[i][j][k][p]=max(dp[i][j][k][p],dp[i-1][j][k][p]+a[h][1]);
  21. }
  22. if(j){
  23. dp[i][j][k][p]=max(dp[i][j][k][p],dp[i][j-1][k][p]+a[h][2]);
  24. }
  25. if(k){
  26. dp[i][j][k][p]=max(dp[i][j][k][p],dp[i][j][k-1][p]+a[h][3]);
  27. }
  28. if(p){
  29. dp[i][j][k][p]=max(dp[i][j][k][p],dp[i][j][k][p-1]+a[h][4]);
  30. }
  31. }
  32. }
  33. }
  34. }
  35. cout<<dp[n/4][n/4][n/4][n/4];
  36. return 0;
  37. }

F 坐火车 (最短路改编)不是很懂,老是卡在9分!!!

最好从头开始学一遍最短路!!!

推荐Dijkstra链式前向星优化:算法小讲堂之最短路算法(Floyd+bellman+SPFA+Dijkstra)

关键是考虑如何求经过城市的数量的最小值!

  1. #include<iostream>
  2. #include<cstring>
  3. #include<queue>
  4. #define int long long
  5. using namespace std;
  6. typedef pair<int,int> PII;
  7. const int N=1e5+10;
  8. const int M=4*N;
  9. const int inf=0x3f3f3f3f;
  10. int n,m;
  11. int h[N],e[M],ne[M],w[M],idx;
  12. int dist[N];
  13. int cnt[N];
  14. bool vis[N];
  15. void init(){
  16. memset(dist,inf,sizeof(dist));
  17. memset(cnt,inf,sizeof(cnt));
  18. memset(h,-1,sizeof(h));
  19. cnt[1]=1;
  20. dist[1]=0;
  21. }
  22. void add(int a,int b,int c){
  23. e[idx]=b;
  24. w[idx]=c;
  25. ne[idx]=h[a];
  26. h[a]=idx++;
  27. }
  28. void dij(){
  29. priority_queue<PII,vector<PII>,greater<PII> > q;
  30. q.push({0,1});
  31. while(q.size()){
  32. PII t=q.top();
  33. q.pop();
  34. int ver=t.second;
  35. if(vis[ver]){
  36. continue;
  37. }
  38. vis[ver]=1;
  39. for(int i=h[ver];i!=-1;i=ne[i]){
  40. int j=e[i];
  41. if(cnt[j]>cnt[ver]+1){
  42. cnt[j]=cnt[ver]+1;
  43. dist[j]=dist[ver]+w[i];
  44. q.push({cnt[j],j});
  45. }else if(cnt[j]==cnt[ver]+1){
  46. if(dist[j]>dist[ver]+w[i]){
  47. dist[j]=dist[ver]+w[i];
  48. q.push({cnt[j],j});
  49. }
  50. }
  51. }
  52. }
  53. }
  54. signed main(){
  55. cin>>n>>m;
  56. init();
  57. while(m--){
  58. int a,b,c;
  59. cin>>a>>b>>c;
  60. add(a,b,c);
  61. add(b,a,c);
  62. }
  63. dij();
  64. cout<<cnt[n]<<' '<<dist[n];
  65. return 0;
  66. }

9分代码: 啊啊啊啊——

  1. #include<iostream>
  2. #include<cstring>
  3. #include<queue>
  4. #define int long long
  5. using namespace std;
  6. const int inf=0x3f3f3f3f;
  7. const int N=100005;
  8. const int M=4*N;
  9. int n,m,cnt;
  10. int head[N],dis[N],sum[N];
  11. bool vis[N];
  12. typedef pair<int,int>Pll;
  13. struct Edge{
  14. int next;
  15. int to;
  16. int w;
  17. }edge[M];
  18. void init(){
  19. memset(vis,0,sizeof(vis));
  20. memset(dis,inf,sizeof(dis));
  21. memset(head,-1,sizeof(head));
  22. memset(sum,inf,sizeof(sum));
  23. cnt=0;
  24. dis[1]=0;
  25. sum[1]=1;
  26. }
  27. void add(int u,int v,int w){
  28. edge[cnt].to=v;
  29. edge[cnt].w=w;
  30. edge[cnt].next=head[u];
  31. head[u]=cnt++;
  32. }
  33. void dij(){
  34. priority_queue<Pll,vector<Pll>,greater<Pll> > q;
  35. q.push(Pll(0,1));
  36. Pll temp;
  37. while(!q.empty()){
  38. temp=q.top();
  39. q.pop();
  40. int u=temp.second;
  41. if(vis[u]){
  42. continue;
  43. }
  44. vis[u]=1;
  45. int t,len;
  46. for(int i=head[u];i!=-1;i=edge[i].next){
  47. t=edge[i].to;
  48. len=edge[i].w;
  49. if(sum[t]>sum[u]+1){
  50. sum[t]=sum[u]+1;
  51. dis[t]=dis[u]+len;
  52. q.push(Pll(dis[t],t));
  53. }else if(sum[t]==sum[u]+1){
  54. if(dis[t]>dis[u]+len){
  55. dis[t]=dis[u]+len;
  56. }
  57. }
  58. }
  59. }
  60. }
  61. signed main(){
  62. init();
  63. cin>>n>>m;
  64. int u,v,w;
  65. for(int i=1;i<=m;i++){
  66. cin>>u>>v>>w;
  67. add(u,v,w);
  68. add(v,u,w);
  69. }
  70. dij();
  71. cout<<sum[n]<<' '<<dis[n];
  72. return 0;
  73. }

G A Xor B Problem again   位运算问题,不懂!!!

学习位运算~~~

  1. #include<iostream>
  2. #define int long long
  3. using namespace std;
  4. const int N=300005;
  5. int n,pre[N],a[N];
  6. signed main(){
  7. cin>>n;
  8. for(int i=1;i<=n;i++){
  9. cin>>a[i];
  10. pre[a[i]]++;//记录每一个数出现的次数
  11. }
  12. //枚举每一个位数(变成二进制之后)
  13. for(int i=0;i<18;i++){
  14. //二进制枚举每(1-1e5)
  15. for(int j=0;j<262144;j++){
  16. // 如果这个数与这个二进制数一样那么
  17. if(j&(1<<i)){
  18. pre[j]+=pre[j^(1<<i)];
  19. }
  20. }
  21. }
  22. int ans=0;
  23. for(int i=1;i<=n;i++){
  24. int x=a[i]^((1<<18)-1);
  25. ans+=pre[x];
  26. }
  27. cout<<ans;
  28. return 0;
  29. }

H  摘苹果

思路:正常思路,模拟,玄学问题,g++编译器超时,clang++编译器能过

可以考虑其他做法进行时间优化!!!

  1. #include<iostream>
  2. #include<cmath>
  3. #define int long long
  4. using namespace std;
  5. const int N=100005;
  6. int a[N];
  7. signed main(){
  8. int n,m;
  9. cin>>n>>m;
  10. for(int i=1;i<=n;i++){
  11. scanf("%lld",&a[i]);
  12. }
  13. while(m--){
  14. int op,l,r,ans;
  15. scanf("%lld%lld%lld",&op,&l,&r);
  16. if(op==1){
  17. for(int i=l;i<=r;i++){
  18. if(a[i]>=10){
  19. a[i]-=((a[i]-1)/3+1);
  20. }
  21. }
  22. }
  23. if(op==2){
  24. ans=0;
  25. for(int i=l;i<=r;i++){
  26. if(a[i]<100){
  27. ans++;
  28. }
  29. }
  30. printf("%lld\n",ans);
  31. }
  32. if(op==3){
  33. ans=0;
  34. for(int i=l;i<=r;i++){
  35. ans+=a[i];
  36. }
  37. printf("%lld\n",ans);
  38. }
  39. }
  40. return 0;
  41. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/232712
推荐阅读
相关标签
  

闽ICP备14008679号