2022年安徽省机器人大赛-程序设计赛道网络预赛-本科组题解
纪念freedive第一次AK的比赛,只不过数据是真的有问题……
A
题目信息:给两个数a、b,可以对a进行如下的操作:a = a + x,x是任意的大于0的奇数, a = a - y, y是任意的大于0的偶数。可以执行任意次数以上的操作。问从a变成b最少需要几次操作?O(1)
1 #include <iostream> 2 using namespace std; 3 4 int main() 5 { 6 long long t, a, b; 7 cin >> t; 8 while(t--) 9 { 10 cin >> a >> b; 11 if(a == b) { 12 cout << 0 << endl; 13 } else if(a > b) { 14 cout << (((a - b) & 1) ? 2 : 1) << endl; 15 } else { 16 cout << (((a - b) & 1) ? 1 : 2) << endl; 17 } 18 } 19 }
B
题目信息:定义数组中的某个数ai如果是特殊的,则满足:在数组中存在一个长度大于等于2的连续子序列,其和为ai。给你一个长度为n的数组,问有多少数是特殊的。O(玄学)
1 #include <cstdio> 2 #include <set> 3 #include <algorithm> 4 using namespace std; 5 6 const int N = 8003; 7 int n, t, a[N], pre[N]; 8 int main() 9 { 10 scanf("%d", &t); 11 while(t--) 12 { 13 scanf("%d", &n); 14 set<int> num; 15 for(int i = 1; i <= n; ++i) 16 { 17 scanf("%d", &a[i]); 18 num.insert(a[i]); 19 pre[i] = pre[i - 1] + a[i]; 20 } 21 for(int i = 0; i < n - 1; ++i) 22 { 23 int j = i + 2; 24 while(j <= n) 25 { 26 int sum = pre[j] - pre[i]; 27 num.erase(sum); 28 set<int>::iterator it = num.upper_bound(sum); 29 if(it == num.end()) 30 break; 31 else 32 j = lower_bound(pre + 1, pre + 1 + n, (*it) + pre[i]) - pre; 33 } 34 } 35 int ans = 0; 36 for(int i = 1; i <= n; ++i) 37 if(num.find(a[i]) == num.end()) 38 ans++; 39 printf("%d\n", ans); 40 } 41 }
C
题目信息:给一个长方体,可以由两个对角顶点坐标确定,一个顶点位于原点(0,0, 0),另一个顶点在点(x1, y1, z1)处。盒子的六个面编号为a1, a2, ..., a6,每个面的正中央印有一个数字x。编号位于框上,如下所示:数字a1写在ZOX平面上的面上;a2写在与a1所在的平面平行的面上;a3写在XOY平面上的面上;a4写在与a3所在的平面平行的面上;a5写在YOZ平面上的面上;a6写在与a5所在的平面平行的面上;此时,你在(x, y, z)处看长方体。请注意,长方体的所有面都不是透明的,你无法通过长方体看到数字且你能看得足够远,求出你能看清所看到的面上数字,求能看到的数字之和。O(1)
1 #include <iostream> 2 using namespace std; 3 int main() { 4 int x, y, z, X, Y, Z, a1, a2, a3, a4, a5, a6, ans = 0; 5 cin >> x >> y >> z >> X >> Y >> Z >> a1 >> a2 >> a3 >> a4 >> a5 >> a6; 6 if(x < 0) ans += a5; else if (x > X) ans += a6; 7 if(y < 0) ans += a1; else if (y > Y) ans += a2; 8 if(z < 0) ans += a3; else if (z > Z) ans += a4; 9 cout << ans << endl; 10 }
D
题目信息:有2N张牌,它们的点数分别为1到2N。小柯拿了其中的N张,小鹏拿了剩下的N张. 小柯和小鹏会进行N轮游戏,在每轮游戏中,小柯和小鹏各出一张牌。出了的牌不能收回。每轮谁的牌点数大谁就赢; 已知小鹏每一轮会出什么牌,试求小柯最多能赢多少轮。O(n)
1 #include <algorithm> 2 #include <iostream> 3 using namespace std; 4 5 const int N = 100005; 6 int n, ans = 0; 7 char book[2 * N]; 8 int main() 9 { 10 cin >> n; 11 for(int i = 0, x; i < n; ++i) 12 { 13 cin >> x; 14 book[x] = 1; 15 } 16 for(int i = 1, j = 1; i <= 2 * n; ++i) 17 if(book[i] == 1) { 18 j = max(j, i + 1); 19 while(book[j] != 0 && j <= 2 * n) 20 ++j; 21 if(j > 2 * n) 22 break; 23 book[j] = 2; 24 ans++; 25 } 26 printf("%d\n", ans); 27 return 0; 28 }
E
题目信息:小怡开了一家蛋糕店,她有n个顾客,每位顾客i都有一个喜好的甜度值a[i](1<=i<=n)。甜度为k的蛋糕,当且仅当|a[i]-k|<=p 时,顾客i才能得到满足。给定n个顾客喜好的甜度值,小怡想知道最多可以让多少顾客得到满足。O(n)
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 const int N = 1000010; 6 int n, p, ans = 1, a[N]; 7 int main() 8 { 9 scanf("%d %d", &n, &p); 10 for(int i = 1; i <= n; ++i) 11 scanf("%d", a + i); 12 sort(a + 1, a + 1 + n); 13 for(int i = 1, j = 1; i <= n; ++i) { 14 for(; j <= n && a[j] - a[i] <= 2 * p; ++j); 15 ans = max(ans , j - i); 16 } 17 printf("%d\n", ans); 18 return 0; 19 }
F
题目信息:给N(1<=N<=30)个正整数,好奇的小明想知道这N个正整数的乘积,是否可以将其分解为2个正整数a和b的乘积,并且a的约数个数与b的约数个数之差为 1 个。O(玄学)(tip:约数一奇一偶,优化时间)
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int maxn=1e6+100; 5 ll a[maxn],aa[maxn],bb[maxn],cc[maxn],n,sc=0,ttt; 6 void dfs(int x){ 7 ll i,j; 8 if(x==ttt+1){ 9 // if(cc[1]==2&&cc[2]==0&&cc[3]==0) 10 // int my=-1; 11 ll all=1,al=1,A=1,B=1; 12 for(i=1;i<=ttt;i++) 13 all=all*(cc[i]+1ll),al=al*((bb[i]-cc[i])+1ll); 14 if(all-al==1){ 15 for(i=1;i<=ttt;i++) 16 for(j=1;j<=cc[i];j++) 17 A=A*aa[i]; 18 for(i=1;i<=ttt;i++) 19 for(j=1;j<=bb[i]-cc[i];j++) 20 B=B*aa[i]; 21 printf("%lld %lld\n",A,all); 22 printf("%lld %lld",B,al); 23 sc=1; 24 return; 25 }else if(al-all==1){ 26 for(i=1;i<=ttt;i++) 27 for(j=1;j<=cc[i];j++) 28 A=A*aa[i]; 29 for(i=1;i<=ttt;i++) 30 for(j=1;j<=bb[i]-cc[i];j++) 31 B=B*aa[i]; 32 printf("%lld %lld\n",B,al); 33 printf("%lld %lld",A,all); 34 sc=1; 35 return; 36 }else return; 37 } 38 if(sc==1)return; 39 for(i=0;i<=bb[x];i+=2){ 40 cc[x]=i; 41 if(sc==1)return; 42 dfs(x+1); 43 if(sc==1)return; 44 } 45 if(sc==1)return; 46 } 47 map<ll,ll>mp; 48 int main(){ 49 ll i,j; 50 scanf("%lld",&n); 51 for(i=1;i<=n;i++){ 52 scanf("%lld",&a[i]); 53 for(j=2;j*j<=a[i];j++){ 54 while(a[i]%j==0){ 55 mp[j]++; 56 a[i]/=j; 57 } 58 }if(a[i]>1)mp[a[i]]++; 59 } 60 ttt=0; 61 map<ll,ll>::iterator it; 62 for(it=mp.begin();it!=mp.end();it++){ 63 ttt++; 64 aa[ttt]=it->first; 65 bb[ttt]=it->second; 66 } 67 dfs(1); 68 return 0; 69 }
G
题目信息:小星是参加防疫的一名志愿者,每天都为在家中被隔离的居民们送蔬菜包。他把每层楼看成一个n*n的矩阵。小星需要将蔬菜包送到位于m层的居民手中,小星想请你帮他计算一下,他能否成功将蔬菜送达。如果能则需要的最少体力,如果不能则输出No。大暴力……累死我了
1 #include<bits/stdc++.h> 2 #define mp make_pair 3 using namespace std; 4 int n,m,tot=0; 5 int dx[5]={0,-1,1,0,0}; 6 int dy[5]={0,0,0,-1,1}; 7 const int maxn=1e5+10; 8 int gg(int x,int y,int z){ 9 return (x-1)*n*n+(y-1)*n+z; 10 } 11 int pp(int x,int y){ 12 if(x<1||y<1||x>n||y>n)return 0; 13 else return 1; 14 } 15 struct EDGE{ 16 int v,next,quan; 17 }edge[500010]; 18 int ind[maxn],vist[maxn],dist[maxn],st,ed; 19 char ss[55][55][55]; 20 void add(int aa,int bb,int cc){ 21 tot++; 22 edge[tot].v=bb; 23 edge[tot].quan=cc; 24 edge[tot].next=ind[aa]; 25 ind[aa]=tot; 26 } 27 void dij(){ 28 int i; 29 priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >pq; 30 memset(dist,127,sizeof(dist)); 31 dist[st]=0; 32 pq.push(mp(0,st)); 33 while(!pq.empty()){ 34 int u=pq.top().second; 35 pq.pop(); 36 if(vist[u])continue; 37 vist[u]=1; 38 for(i=ind[u];i!=-1;i=edge[i].next){ 39 int v=edge[i].v; 40 if(vist[v])continue; 41 if(dist[v]>dist[u]+edge[i].quan){ 42 dist[v]=dist[u]+edge[i].quan; 43 pq.push(mp(dist[v],v)); 44 } 45 } 46 } 47 } 48 int main(){ 49 int o,i,j,a,b; 50 memset(ind,-1,sizeof(ind)); 51 scanf("%d%d",&m,&n); 52 for(o=1;o<=m;o++){ 53 for(i=1;i<=n;i++) 54 scanf("%s",ss[o][i]+1); 55 for(i=1;i<=n;i++){ 56 for(j=1;j<=n;j++){ 57 //if(i==2&&j==1) 58 // int my=-1; 59 if(ss[o][i][j]=='#')continue; 60 for(a=1;a<=4;a++){ 61 int ni=i+dx[a],nj=j+dy[a]; 62 int ppp=0; 63 if(!pp(ni,nj))continue; 64 if(ss[o][ni][nj]=='.'||ss[o][ni][nj]=='E'||ss[o][ni][nj]=='S'||ss[o][ni][nj]=='U'){ 65 add(gg(o,i,j),gg(o,ni,nj),1); 66 ppp=1; 67 } 68 if(ss[o][ni][nj]=='#'){ 69 ppp=2; 70 } 71 if(ppp==2){ 72 int nni=ni+dx[a],nnj=nj+dy[a]; 73 if(nni==i&&nnj==j)continue; 74 if(!pp(nni,nnj))continue; 75 if(ss[o][nni][nnj]=='.'||ss[o][nni][nnj]=='E'||ss[o][nni][nnj]=='S'||ss[o][nni][nnj]=='U') 76 add(gg(o,i,j),gg(o,nni,nnj),3); 77 } 78 else{ 79 for(b=1;b<=4;b++){ 80 int nni=ni+dx[b],nnj=nj+dy[b]; 81 if(nni==i&&nnj==j)continue; 82 if(!pp(nni,nnj))continue; 83 if(ss[o][nni][nnj]=='.'||ss[o][nni][nnj]=='E'||ss[o][nni][nnj]=='S'||ss[o][nni][nnj]=='U') 84 add(gg(o,i,j),gg(o,nni,nnj),1); 85 } 86 } 87 } 88 } 89 } 90 } 91 int tmp=m*n*n+5; 92 for(o=1;o<m;o++){ 93 // int aa,bb,cc,dd; 94 // tmp++; 95 for(i=1;i<=n;i++)for(j=1;j<=n;j++)if(ss[o][i][j]=='U'){ 96 add(gg(o,i,j),gg(o+1,i,j),0); 97 } 98 } 99 for(i=1;i<=n;i++)for(j=1;j<=n;j++){ 100 if(ss[1][i][j]=='S')st=gg(1,i,j); 101 if(ss[m][i][j]=='E')ed=gg(m,i,j); 102 } 103 dij(); 104 if(dist[ed]==dist[0])printf("No"); 105 else printf("%d",dist[ed]); 106 return 0; 107 }
H
题目信息:小星是参加防疫的一名志愿者,每天都为在家中被隔离的居民们送蔬菜包。他把每层楼看成一个n*n的矩阵。小星需要将蔬菜包送到位于m层的居民手中,小星想请你帮他计算一下,他能否成功将蔬菜送达。如果能则需要的最少体力,如果不能则输出No。O(n)
1 #include <cstdio> 2 #include <map> 3 using namespace std; 4 5 const int N = 200010; 6 int n, a[N], k, ans = 0; 7 map<int, int> bk; 8 int main() 9 { 10 scanf("%d", &n); 11 for(int i = 1, x; i <= n; ++i) 12 { 13 scanf("%d", &x); 14 a[i] = a[i - 1] ^ x; 15 } 16 scanf("%d", &k); 17 bk[0] = 1; 18 for(int i = 1; i <= n; ++i) 19 { 20 ans += bk[a[i]^k]; 21 bk[a[i]]++; 22 } 23 printf("%d\n", ans); 24 return 0; 25 }