【PAT刷题】快速产出垃圾——2020-2-2
算法笔记3.1节
万万没想到刚开始就有A级题,英语阅读理解始める!
A1042
(1)自己尝试+参考思路
1 #include <cstdio> 2 #include <string> 3 4 char mp[5] = {'S','H','C','D','J'}; //很有趣的操作 5 6 int main(){ 7 int k; 8 scanf("%d",&k); 9 int start[55] = {0}; 10 int next[55] = {0}; 11 for(int j=1;j<=54;j++){ 12 int temp; 13 scanf("%d",&temp); 14 start[j] = j; 15 next[j] = temp; 16 } 17 int end[55] = {0}; 18 for(int i=0;i<k;i++){ 19 for(int j=1;j<=54;j++){ 20 end[next[j]] =start[j]; 21 } 22 for(int j=1;j<=54;j++){ 23 start[j] =end[j]; 24 } 25 } 26 for(int i=1;i<=54;i++){ 27 printf("%c%d",mp[(start[i]-1)/13],(start[i]-1)%13+1); 28 if(i!=54) printf(" "); 29 } 30 31 }
这题需要开三个数组是没想到的,需要有一个next数组是不变的,否则每次循环的时候没法保留原始的交换顺序。
总得来讲a级题的思考能力要求确实提高了很多。
然后就是打印的方式很值得学习 。
尽管需要说的不多,但是这道题需要当作一个重点以后复习。
A1046
总之二重循环会超时,没啥办法,错的就不贴了。看下答案,
根据答案中要求查询的复杂度为O(1),所以需要预处理。
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 const int MAXN = 100005; 6 int dis[MAXN],A[MAXN]; 7 int main(){ 8 int sum =0,query,n,left,right; 9 scanf("%d",&n); 10 for(int i=1;i<=n;i++){ 11 scanf("%d",&A[i]); 12 sum += A[i]; //累加sum 13 dis[i] = sum; //预处理dis数组,防止超时。 14 } 15 scanf("%d",&query); 16 for(int i=0;i<query;i++){ //query个查询 17 scanf("%d%d",&left,&right); //left->right; 18 if(left>right) swap(left,right); //algorithm中的函数 19 int temp = dis[right-1]- dis[left-1]; 20 printf("%d\n",min(temp,sum-temp)); 21 } 22 return 0; 23 }
这题最好能背过,也算是正式开启算法学习的一道题了 。
总得来讲需要注意以下几点:
①给数组开空间的时候不用太在意大小。
②对数组进行预处理,多存几个数组,这样最节约时间。
③记录总距离,然后通过总距离减当前距离获得另一个距离。这个数据结构其简化后只有顺时针和逆时针的一条线,答案已经是抽象的最高层次了。
A1065
肯定有坑,不知道在哪,写完部分正确,看答案找坑。
思路:
long long的范围是[-2^63,2^63),两个整数相加可能会溢出。在计算机组成原理中会指出,如果两个正数之和等于负数或是两个负数之和等于正数,那么就是溢出。对于溢出后的具体范围,可以进行如下分析:
① 当A+B>=263时,显然有A+B>C成立,但是A+B会因超过long long的正向最大值而发生正溢出。由于题目给定的A和B的最大均为263-1,故A+B的最大值为264-2,因此使用long long存储正溢出后的值的区间为[-263,-2](由(2^64-2)%(2^64)=-2可得右边界)。所以当A>0,B>0,A+B<0时为正溢出,输出true。
②当A+B<-263时,显然有A+B<C成立,但A+B会因超过long long的负向最小值而发生负溢出。由于题目给定的A和B的最小均为-264,故A+B最小为-264。因此使用long long负溢出时后的值的区间为[0,263)(由(-264)%264=可得右边界)。
所以当A<0,B<0,A+B>=0时为负溢出,输出false。
③当没有溢出的情况下,正常考虑。
注意点:
①经测试,数据中没有A或B取到2^63的情况,因此题目中的数据范围可能是写错了,应该是[-2^63,2^63)才更符合数据,否则就要用带负数的大整数运算了(因为long long存储2^63时会自动变成-2^63,无法区分左右边界)。
②A+B必须存放到long long型变量中才能与C进行比较,而不可以在if条件中直接相加与C比较,否则会造成后两组数据错误(?)。
然后答案差不多就这样了。
1 #include <cstdio> 2 3 int main(){ 4 int n; 5 scanf("%d",&n); 6 for(int i=1;i<=n;i++){ 7 long long a,b,c; 8 scanf("%lld%lld%lld",&a,&b,&c); 9 long long res = a + b; 10 bool flag; 11 if(a>0 && b>0 && res<0) flag = true; //正溢出为true 12 else if(a<0 && b<0 && res>=0) flag = false; //负溢出为false 13 else if(res>c) flag = true; 14 else flag =false; 15 if(flag == true){ 16 printf("Case #%d: true\n",i); 17 } 18 else{ 19 printf("Case #%d: false\n",i); 20 } 21 } 22 }
B1010
。。都标红好了
(1)自己尝试
1 #include <cstdio> 2 3 //需要用while EOF读入数据 4 5 int main(){ 6 int k,e; 7 while(scanf("%d%d",&k,&e)!=EOF){ 8 if(e!=0) printf("%d %d ",k*e,e-1); 9 } 10 }
想当然地写了两行,发现跳进了深坑,这个没啥太好办法解决最后的空格问题。
去参考下答案。
(2)参考答案
1 #include <cstdio> 2 3 //需要用while EOF读入数据 4 5 int main(){ 6 int a[1010] = {0}; 7 int k,e,count=0; //k为系数,e为指数,count计数不为零的导数的个数。 8 while(scanf("%d%d",&k,&e)!=EOF){ 9 a[e] = k; 10 } 11 a[0] =0; //零次求导之后直接为0。 12 for(int i=1;i<=1000;i++){ 13 a[i-1] = a[i]*i; //求导公式 14 a[i] = 0; //此句不可省 15 if(a[i-1]!=0) count++; 16 } 17 if(count==0) printf("0 0"); //特例 18 else{ 19 for(int i=1000;i>=0;i--){ //指数从高到低输出 20 if(a[i] != 0){ 21 printf("%d %d",a[i],i); 22 count--; 23 if(count != 0) printf(" "); 24 } 25 } 26 } 27 return 0; 28 }
实际上这题可以自己写下试试,不过那个“如果求导之后没有任何非零项,需要输出 0 0,这是本题的一个陷阱应该发现不了。总得来讲学到怎么用while EOF是最主要的。
A1002
(1)自己尝试
1 1002 2 相加为0的值不出现,注意最前边也需要改 3 #include<iostream> 4 #include<set> 5 using namespace std; 6 double num[10005]; 7 int main(){ 8 int n; 9 set<int>s; 10 cin>>n; 11 for(int i=0;i<n;i++){ 12 int a ; 13 double b; 14 cin>>a>>b; 15 num[a]+=b; 16 } 17 cin>>n; 18 for(int i=0;i<n;i++){ 19 int a ; 20 double b; 21 cin>>a>>b; 22 num[a]+=b; 23 } 24 int count=0; 25 for(int i=0;i<10005;i++){ 26 if(num[i]!=0){ 27 count++; 28 } 29 } 30 cout<<count; 31 for(int i=10000;i>=0;i--){ 32 if(num[i]!=0){ 33 printf(" %d %0.1f", i, num[i]); 34 //cout<<" "<<i<<" "<<num[i]; 35 } 36 } 37 return 0; 38 }
这题没太多值得说的。
A1009
注意一下参考答案使用结构体的写法。
1 #include <cstdio> 2 struct Ploy{ 3 int exp;//指数 4 double cof; //系数 5 } ploy[1001]; //第一个多项式 6 7 double ans[2001];//存放结果 8 int main(){ 9 int n,m,number = 0; 10 scanf("%d",&n); //第一个多项式中非零系数的项数。 11 for(int i=0;i<n;i++){ 12 scanf("%d %lf",&ploy[i].exp,&ploy[i].cof); 13 } 14 scanf("%d",&m); //第二个多项式中非零系数的项数。 15 for(int i=0;i<m;i++){ 16 int exp; 17 double cof; 18 scanf("%d %lf",&exp,&cof); //第二个多项式的指数和系数 19 for(int j=0;j<n;j++){ //与第一个多项式中的每一项相加 20 ans[exp+ploy[j].exp] += (cof*ploy[j].cof); 21 } 22 } 23 for(int i=0;i<=2000;i++){ 24 if(ans[i]!=0.0) number++; //积累非零系数的项数 25 } 26 printf("%d",number); 27 for(int i=2000;i>=0;i--){ 28 if(ans[i]!=0.0){ 29 printf(" %d %.1f",i,ans[i]); 30 } 31 } 32 33 }

浙公网安备 33010602011771号