个人学习记录,代码难免不尽人意。
在PTA买了浙软2020年的保研上机真题+时光机做了做,20年的明显要比19年的难一些,我用了差不多2小时多一点做完了,最后得分90分,在当年排名26左右。下面是4道题和我的做法
7-1 Standard Form of Polynomial
Sample Input:
3
-1 4 -1
Sample Output:
-2 -7 -4
#include<iostream>
#include<cstdio>
#include<vector>
int num[15];
using namespace std;
int main(){int n;scanf("%d",&n);for(int i=0;i<n;i++){scanf("%d",&num[i]);}vector<int> res,temp;res.push_back(1);res.push_back(-num[0]);for(int i=1;i<n;i++){temp.clear();//别忘了;temp.push_back(1);temp.push_back(-num[i]);//注意加负 vector<int> v1,v2;for(int j=0;j<res.size();j++){v1.push_back(res[j]*temp[0]);v2.push_back(res[j]*temp[1]);}res.clear();res.push_back(v1[0]);for(int j=1;j<v1.size();j++){res.push_back(v1[j]+v2[j-1]);}res.push_back(v2[v2.size()-1]);}for(int i=1;i<res.size();i++){printf("%d",res[i]);if(i!=res.size()-1) printf(" ");else printf("\n");}
}
第一题难度适中,如果一开始没有思路的话也不要着急,时间是很充裕的。题干的意思是给了化简的多项式(x-n1)(x-n2)(x-n3)·······,我们需要将他们转换成一般形式再输出。我们可以这样分析,用temp保存每次计算的系数项,然后和下一个括号相乘,然后再错位相加即可。
7-2 Distance of Triples
Output Specification:
For each case, print in a line MinD(a, b, c) = d, where (a, b, c) are the triples that has the minimum distance, and d is the corresponding distance. If the solution is not unique, output the largest triples.
Sample Input:
4 4 6
0 9 -1 11
10 -25 11 -10
9 2 41 17 12 30
Sample Output:
MinD(11, 11, 12) = 2
Hint:
Notice that there are two solutions. The other one is MinD(9, 10, 9) = 2. Since (11, 11, 12) is larger, this one must be printed out.
#include<iostream>
#include<cstdio>
#include<vector>
#include<unordered_set>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
const int maxn=30010;
vector<pair<int,char> > v;
bool cmp(pair<int,char> a,pair<int,char> b){if(a.first!=b.first)return a.first<b.first;else return a.second<b.second;
}
int main(){int a,b,c;scanf("%d %d %d",&a,&b,&c);for(int i=0;i<a;i++){int num;scanf("%d",&num);v.push_back(make_pair(num,'a'));}for(int i=0;i<b;i++){int num;scanf("%d",&num);v.push_back(make_pair(num,'b'));}for(int i=0;i<c;i++){int num;scanf("%d",&num);v.push_back(make_pair(num,'c'));}sort(v.begin(),v.end(),cmp);int min=1000000000;int arr[3]={0};for(int i=0;i<v.size()-2;i++){char tag1=v[i].second;char tag2=v[i+1].second;char tag3=v[i+2].second;if(tag1!=tag2&&tag2!=tag3&&tag3!=tag2){int num1=v[i].first;int num2=v[i+1].first;int num3=v[i+2].first;int res=abs(num1-num2)+abs(num2-num3)+abs(num3-num1);if(res<=min){min=res;arr[tag1-'a']=num1;arr[tag2-'a']=num2;arr[tag3-'a']=num3;}}}printf("MinD(%d, %d, %d) = %d\n",arr[0],arr[1],arr[2],min);
}
这道题我得了19分,说实话确实有点不大会做,我只想到了将a,b,c放到一个数组中从小到大排列,然后觉得满足题意的a,b,c应该是挨在一起的,但是这样子并不行。
7-3 Partial School Ranking
In a Group Programming Contest, each university is supposed to send n students who must compete independently. The universities are ranked according to the total score of their students. Your job is to generate the ranklist.
It sounds like a simple problem, but what makes it complicated is that we have lost all the teams’ information! What we have is a list of only some of the students’ scores, and some photos taken from the contest sites which shows several students with the same university badge. You just have to recover the ranklist as much as you can.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤1000). Then N lines follow, each gives the information of a student in the format:
ID k teammate
1
⋯teammate
k
Score
where ID is a unique 4-digit identification number for a student; k (0≤k≤5) is the number of teammates of this student in a photo; teammate
i
's are the ID’s of his/her teammate; and Score is this stdent’s score which is in the range [0, 400].
It is guaranteed that each ID with a Score is given only once.
Output Specification:
For each case, first print in a line the number of universities (all the students that are related directly or indirectly as teammates are considered in the same university). Then output the partial school ranking in the format:
ID S Score
total
where ID is the smallest student ID in the university; S is the total number of its students; and Score
total
is the total score that can be recovered for that university. The universities must be given in descending order of their Score
total
, or in ascending order of S if there is a tie, or in ascending order of ID if there is still a tie.
Sample Input:
11
7456 3 7457 7458 7459 157
6666 3 5551 5552 7777 100
1234 3 5678 9012 0002 80
8888 0 340
2468 3 0001 0004 2222 110
7777 1 6666 57
3721 1 2333 30
9012 3 1236 1235 1234 10
1235 2 5678 9012 50
2222 4 1236 2468 6661 6662 16
2333 4 3721 6661 6662 6663 44
Sample Output:
4
8888 1 340
0001 15 340
5551 4 157
7456 4 157
#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=10010;
int father[maxn];
int score[maxn]={0};
int findfather(int n){if(father[n]==n) return n;else return findfather(father[n]);
}
void merge(int a,int b){int fa=findfather(a);int fb=findfather(b);if(fa!=fb){father[fa]=fb;}
}
set<int> s;
struct node{int fa;int id;int num;int score;
};
vector<node> res;
set<int> ids;
bool cmp(node a,node b){if(a.score!=b.score) return a.score>b.score;else if(a.num!=b.num) return a.num<b.num;else return a.id<b.id;
}
int main(){for(int i=0;i<maxn;i++) father[i]=i;int n;scanf("%d",&n);for(int i=0;i<n;i++){int id,k;scanf("%d %d",&id,&k);s.insert(id);for(int j=0;j<k;j++){int a;scanf("%d",&a);s.insert(a);merge(a,id);}int b;scanf("%d",&b);score[id]=b;}for(set<int>::iterator it=s.begin();it!=s.end();it++){int id=*it;int fa=findfather(id);if(ids.find(fa)==ids.end()){ids.insert(fa);node no;no.fa=fa;no.id=id;no.num=1;no.score=score[id];res.push_back(no);}else{for(int i=0;i<res.size();i++){if(res[i].fa==fa){if(res[i].id>id) res[i].id=id;res[i].num++;res[i].score+=score[id];}}}}sort(res.begin(),res.end(),cmp);printf("%d\n",res.size());for(int i=0;i<res.size();i++){printf("%04d %d %d",res[i].id,res[i].num,res[i].score);if(i!=res.size()-1) printf("\n");}
}
一开始我觉得我的做法会超时,结果满分通过了。本题就是很常规的存储加排序。
7-4 Shopping With Coupons
Sample Input:
4 30
12 20 15 10
9 6 8 7
Sample Output:
8 2
#include<iostream>
#include<cstdio>
#include<vector>
#include<unordered_set>
#include<algorithm>
#include<map>
using namespace std;
const int maxn=100010;
int cost[maxn];
int coupon[maxn];
int mp[maxn];
int main(){int n,money;scanf("%d %d",&n,&money);for(int i=0;i<n;i++){scanf("%d",&cost[i]);}for(int i=0;i<n;i++){scanf("%d",&coupon[i]);}for(int i=0;i<n;i++){for(int j=0;j<n;j++){int a=cost[i]-coupon[j];if(a<=money){mp[a]++;}}}int cnt=0;bool flag=false;for(int i=0;i<maxn;i++){if(mp[i]!=0){int pay=i;int len=mp[pay];for(int i=0;i<len;i++){if(money>=pay){money-=pay;cnt++;}else{//及时剪枝 flag=true;break;}}}if(flag) break;}printf("%d %d\n",cnt,money);
}
我的做法26/30,有一个测试点显示超时了,但是我想不出在代码基础上可以优化的地方了,感觉如果想不超时只能换一个思路了,这个地方就不细究了。
总的来说题目有难度,但是如果静下心来,不受时间的和结果的压力的话,是可以取得比较乐观的分数的。