胡凡 《算法笔记》 上机实战训练指南 3.1
持续更新中 , 菜鸡的刷题笔记…
大学到现在了还没咋好好刷过题,该push自己了…
文章目录
- 胡凡 《算法笔记》 上机实战训练指南 3.1
- 3.1 简单模拟
- 【PAT B1001】害死人不偿命的(3n+1)猜想
- 【PAT B1032】挖掘机技术哪家强
- 【PAT B1011】A+B 和 C
- 【PAT B1016】部分A+B
- 【PAT B1026】程序运行时间
- 【PAT B1046】划拳
- 【PAT B1008】数组元素循环右移问题
- 【PAT B1012】数字分类
- 【PAT B1018】锤子剪刀布
- 【PAT A1042】Shuffling Machine
- 【PAT A1046】Shortest Distance
- 【PAT A1065】A+B and C(64bit)
- 【PAT B1010】一元多项式求导
- 【PAT A1002】A+B for Polynomials
- 【PAT A1009】Product of Polynomials
- 参考资料
3.1 简单模拟
【PAT B1001】害死人不偿命的(3n+1)猜想
-
题目链接
-
AC代码
#include <iostream> using namespace std; int main() { int n; scanf("%d",&n); int res; int step = 0; while( n != 1) { if(n % 2 == 0) { n /= 2; } else { n = ( 3 * n + 1) / 2; } step += 1; } cout << step; return 0; }
-
简洁写法
if (n % 2) { n = (n * 3 + 1) / 2; } else { n /= 2; }
【PAT B1032】挖掘机技术哪家强
-
题目链接
-
一开始的代码
- 只过了一个测试点
#include <cstdio> int score[10010]={0}; int main() { int N; scanf("%d",&N); int maxScore; int index,num; int residx ; for(int i = 1; i <= N; i ++) { scanf("%d%d",&index,&num); score[index]+=num; } maxScore = score[1]; for (int i = 2; i <= N; i ++) { if(score[i] > maxScore) { maxScore = score[i]; residx = i; } } printf("%d %d",residx,score[residx]); return 0; }
-
上面的代码的漏洞在于,如果第一个学校的总分就是最高的,无法输出
-
于是,将自己的代码里面的 residx初始化为1,但还是有数据点没通过
- 去参考了这个:【PAT B1032】挖掘机技术哪家强 - Chilan Yuk的文章 - 知乎 https://zhuanlan.zhihu.com/p/397334909
-
看了半天,不知道为啥错,仔细一看,数组开小了…
- 10的5次方… 就开了个10010… 蚌埠住了… 这里浪费了一堆时间
-
AC代码
#include <cstdio> int score[100010]; int main() { int N; scanf("%d",&N); int maxScore; int index,num; int residx = 1; for(int i = 1; i <= N; i ++) { scanf("%d%d",&index,&num); score[index]+=num; } maxScore = score[1]; for (int i = 1; i <= N; i ++) { if(score[i] >= maxScore) { maxScore = score[i]; residx = i; } } printf("%d %d",residx,score[residx]); return 0; }
-
另外,自己写的代码 两个for循环其实可以合并 ,就像题解里面只写了一个while循环那样
#include <cstdio> int score[100010]; int main() { int N; scanf("%d",&N); int maxScore=0; int index,num; int residx = 1; for(int i = 1; i <= N; i ++) { scanf("%d%d",&index,&num); score[index]+=num; if(score[i] > maxScore) { maxScore = score[i]; residx = i; } } printf("%d %d",residx,score[residx]); return 0; }
【PAT B1011】A+B 和 C
-
题目链接
-
AC代码
#include <iostream> using namespace std; int main() { int T; long long A,B,C; cin >> T; int i=1; while(T--) { cin>> A >> B >> C; if(A + B > C) cout<<"Case #"<<i<<": true"<<endl; else cout<<"Case #"<<i<<": false"<<endl; i+=1; } return 0; }
【PAT B1016】部分A+B
-
题目链接
-
AC代码
#include <iostream> using namespace std; int getN(int a, int b) { int p = 0; int num = 1; while(a) { if( a % 10 == b) { p += num*b; num *= 10; } a /= 10; } return p; } int main() { int A,D_A,B,D_B; int P_A=0,P_B=0; cin >> A >> D_A >> B >> D_B; int numA=1; int numB=1; P_A = getN(A,D_A); P_B = getN(B,D_B); cout<< P_A + P_B <<endl; return 0; }
【PAT B1026】程序运行时间
-
题目链接
-
思路比较顺畅,但是一开始的答案格式错了,时分秒的输出要保证不足两位时高位用0 补充
-
错误格式代码
#include <iostream> using namespace std; int main() { int C1, C2; cin >> C1 >> C2; double S = (C2-C1)/100.0; int T; int hh, mm , ss; if(S < (C2-C1)/100+0.5) { T = (C2-C1) / 100; } else { T = (C2-C1) / 100 + 1; } hh = T / 3600; mm = T / 60 - hh * 60; ss = T - hh * 3600 - mm * 60; printf("%d:%d:%d",hh,mm,ss); }
-
正确AC代码
#include <iostream> using namespace std; int main() { int C1, C2; cin >> C1 >> C2; double S = (C2-C1)/100.0; int T; int hh, mm , ss; if(S < (C2-C1)/100+0.5) { T = (C2-C1) / 100; } else { T = (C2-C1) / 100 + 1; } hh = T / 3600; mm = T / 60 - hh * 60; ss = T - hh * 3600 - mm * 60; printf("%02d:%02d:%02d",hh,mm,ss); }
-
-
但感觉自己的代码还是不够简洁
这是参考链接里面那位知乎博主写的
#include <iostream> #include <cstdio> #include <cmath> using namespace std; int main() { int C1, C2; cin >> C1 >> C2; int time = round((C2 - C1)/100.0); printf("%02d:%02d:%02d\n",time/3600,time%3600/60,time%60); }
这本书上给的答案👇
书上避免浮点数运算的写法: C2-C1的末两位不少于50时,说明除以100后需要进位
#include <iostream> #include <cstdio> #include <cmath> using namespace std; int main() { int C1, C2; cin >> C1 >> C2; int ans = C2 - C1; if( ans % 100 >= 50) { ans = ans / 100 + 1; } else { ans = ans / 100; } // int time = round((C2 - C1)/100.0); printf("%02d:%02d:%02d\n",ans /3600,ans %3600/60,ans%60); }
【PAT B1046】划拳
-
题目链接
-
AC代码
#include <iostream> #include <cstdio> using namespace std; void getCount(int jha, int jhu, int yha, int yhu,int& jf , int& yf) { if((jhu == jha + yha)&&(yhu == jha + yha) || (jhu != jha + yha)&&(yhu != jha + yha)) return; else { if(jhu == jha + yha) yf += 1; if(yhu == jha + yha) jf += 1; } } int main() { int N; int jha,jhu,yha,yhu; int jf = 0 , yf = 0; cin >> N; while(N--) { cin >> jha >> jhu >> yha >> yhu; getCount(jha,jhu,yha,yhu,jf,yf); } cout<<jf<<" "<<yf; return 0; }
想到引用不错,但还是感觉自己写的有点复杂
-
书上答案👇比较简洁
#include <iostream> #include <cstdio> using namespace std; int main() { int N; //条数 cin >> N; int failA, failB; //输的次数 for(int i = 0 ;i < N ; i++) { int a1,a2 ,b1, b2; cin>> a1 >> a2 >> b1 >> b2; //甲猜中乙没有猜中 if(a1 + b1 == a2 && a1 + b1 !=b2) { failB++; } //甲没猜中乙猜中了 else if( a1 + b1 != a2 && a1 + b1 == b2) { failA ++; } } cout << failA << " " << failB; return 0; }
既然平局不加分,那就直接表示一个人赢的情况,代码更简洁
【PAT B1008】数组元素循环右移问题
-
题目链接
-
AC居然搞了大半天…
一开始只用一个数组的方法想了大半天… 然后开一个数组的也耗费大半天…(不过其实违背题意了…题目里说不允许使用另外数组的前提下) 因为一开始数组a从i=1开始搞的…
#include <iostream> using namespace std; int N; int M; int a[110]; int b[110]; int main() { cin >> N >> M; for(int i = 0; i <= N-1; i ++) { cin >> a[i]; } // int temp; // for(int i = 1; i <= N; i ++) // { // temp = a[i]; // a[i] = a[(i+M)%N]; // a[(i+M)%N] = temp; // } for(int i = 0; i <= N-1; i ++) { b[(i+M)%N ] = a[i]; } //temp = a ; a = b; b = temp; for(int i = 0; i <= N-2; i ++) { cout << b[i] << " "; } cout << b[N-1]; return 0; }
-
知乎博主的做法
思路nb… 启发很大
【PAT B1008】数组元素循环右移问题 - Chilan Yuk的文章 - 知乎 https://zhuanlan.zhihu.com/p/398355139
#include <iostream> using namespace std; int main() { int N, M; int arr[105]; cin >> N >> M; for(int i = 0; i < N; i ++) cin >> arr[(i+M)%N]; cout << arr[0]; if(N > 1) for(int i = 1; i < N; i ++) cout << " " << arr[i]; }
-
书上的思路
其实也是只管输出就行, cnt与N比较大小是用来控制格式
cnt记录已经输出的数的个数
右移M位,就相当于N-M号元素变成了新数组的第一个元素
于是先输出N-M到N-1号元素,再输出0到N-M-1号即可
#include <iostream> using namespace std; int main() { int a[110]; int N, M, cnt = 0; cin >> N >> M; M = M % N; for( int i = 0 ; i < N; i++) { cin >> a[i]; } for( int i = N - M; i < N; i++) { cout << a[i]; cnt++; if(cnt < N ) cout << " "; } for( int i = 0; i < N - M; i++) { cout << a[i]; cnt ++; if(cnt < N ) cout << " "; } return 0; }
【PAT B1012】数字分类
-
题目链接
-
一开始的代码
#include <iostream> #include <cstdio> using namespace std; double A[6]; int cnt[6]; //判断每一类是否有数字 int num[1010]; int main() { int N; int max = 0; cin >> N; int flag = 1; for(int i = 1; i <= N; i++) { cin >> num[i]; } for(int i = 1; i <= N; i++) { if(num[i] % 10 == 0) { cnt[1] += 1; A[1] += num[i]; } else if(num[i] % 5 == 1) { cnt[2] += 1; A[2] += flag*num[i]; flag *= -1; } else if(num[i] % 5 == 2) { cnt[3] += 1; A[3] += 1; } else if(num[i] % 5 == 3) { cnt[4] += 1; A[4] += num[i]/3.0; } else if(num[i] % 5 == 4) { cnt[5] += 1; //可有可无 if(num[i] > max) max = num[i]; A[5] = max; } } for(int i = 1; i <= 3; i++) { if(cnt[i] == 0) { cout<<"N "; } else cout << A[i] << " "; } if(cnt[4] == 0) cout << "N "; else printf("%.1f ",A[4]); cout<< A[5]; return 0; }
在这之前还犯了一个窒息的错误
循环输入数组的时候,循环体里面的语句写成了
cin >> num[1]
在这种时候,最好借助cout来检查一下,果真,
一开始遍历输出就发现不对劲
-
浅看了一下答案,发现对第五个是否有数字都进行了判断…于是加上去了
结果果真多过了几个测试样例
-
发现错误后AC了,难蚌
这里为啥除以3.0???… 应该最后的和除以cnt[4]呀!!!
估计是因为看到题目里面写的余3…所以想当然的写成了除以3.0… 然后和高中一样 经常犯这种错误😅
还有一开始怀疑cnt[5]的作用…
如果没有除5余4 的数的话,就是0…
AC代码如下
#include <iostream> #include <cstdio> using namespace std; double A[6]; int cnt[6]; //判断每一类是否有数字 int num[1010]; int main() { int N; int max = 0; cin >> N; int flag = 1; for(int i = 1; i <= N; i++) { cin >> num[i]; } for(int i = 1; i <= N; i++) { if(num[i] % 10 == 0) { cnt[1] += 1; A[1] += num[i]; } else if(num[i] % 5 == 1) { cnt[2] += 1; A[2] += flag*num[i]; flag *= -1; } else if(num[i] % 5 == 2) { cnt[3] += 1; A[3] += 1; } else if(num[i] % 5 == 3) { cnt[4] += 1; A[4] += num[i]; } else if(num[i] % 5 == 4) { cnt[5] += 1; if(num[i] > max) max = num[i]; A[5] = max; } } for(int i = 1; i <= 3; i++) { if(cnt[i] == 0) { cout<<"N "; } else cout << A[i] << " "; } if(cnt[4] == 0) cout << "N "; else printf("%.1f ",A[4]/cnt[4]); if(cnt[5] == 0) //cnt[5]好像不会等于0呀? 但是这句去掉直接错好几个测试样例 cout << "N"; else cout<< A[5]; return 0; }
【PAT B1018】锤子剪刀布
-
题目链接
-
emmm 第一次AC的代码 屎山代码
用algorithm的max_element找出数组最大值的元素及其下标
#include <iostream> #include <algorithm> using namespace std; int N; int AW[3]; //甲胜平负次数 int BW[3]; //乙胜平负次数 int AR[3]; //甲的三个手势的获胜次数 int BR[3]; //乙的三个手势的获胜次数 char A[100010]; char B[100010]; char s[3]={'C','J','B'}; //其实胜平负只需要一个数组就行. void compareAB(char a, char b) { if(a == b) { AW[1] +=1; BW[1] +=1; } else { if(a == 'C' && b == 'J') { AW[0]+=1; BW[2]+=1; AR[0]+=1; } else if(a == 'C' && b == 'B') { AW[2]+=1; BW[0]+=1; BR[2]+=1; } else if(a == 'J' && b == 'C') { AW[2]+=1; BW[0]+=1; BR[0]+=1; } else if(a == 'J' && b == 'B') { AW[0]+=1; BW[2]+=1; // AW[1]+=1;.... 唉 AR写成AW 半天没检查出来 AR[1]+=1; } else if(a == 'B' && b == 'C') { AW[0]+=1; BW[2]+=1; AR[2]+=1; } else if(a == 'B' && b == 'J') { AW[2]+=1; BW[0]+=1; BR[1]+=1; } } } void print() { // int maxAindex = max_element(AR,AR+3)-AR; // int maxBindex = max_element(BR,BR+3)-BR; // cout << s[maxAindex] << " " << s[maxBindex]; //还要考虑字典序... 也许直接写if还更方便? //字典序,那就先从B C J开始判断 也就是 2 0 1的顺序 int maxAele = *max_element(AR,AR+3); if(AR[2]==maxAele) cout<<s[2]<<" "; else if(AR[0]==maxAele) cout<<s[0]<<" "; else cout<<s[1]<<" "; // if(AR[0] >= AR[1] && AR[0] >= ) int maxBele = *max_element(BR,BR+3); if(BR[2]==maxBele) cout<<s[2]; else if(BR[0]==maxBele) cout<<s[0]; else cout<<s[1]; } int main() { cin >> N; for(int i = 1; i <= N; i++) { cin >> A[i] >> B[i]; compareAB(A[i],B[i]); } for(int i = 0; i <= 1; i++) { cout << AW[i] <<" "; } cout << AW[2] << endl; for(int i = 0; i <= 1; i++) { cout << BW[i] <<" "; } cout << BW[2] << endl; //可以用max嘛?👇 STL里面有直接返回数组最大值的下标的嘛 print(); return 0; }
【PAT A1042】Shuffling Machine
-
题目链接
-
一时半会儿没搞出来
-
题目算是看懂了…
- 先输入洗牌的次数
- 然后输入给定的洗牌顺序
- 在每一次洗牌中
- 第i个位置的牌要移动到第j个位置
- 而牌的初始顺序是啥捏
- 在每一次洗牌中
S1, S2, ..., S13, H1, H2, ..., H13, C1, C2, ..., C13, D1, D2, ..., D13, J1, J2
-
但是代码好像还是不会写…
先把👇这个代码看懂了
https://www.cnblogs.com/claremore/p/6547993.html#:~:text=Shuffling Machine (20) Shuffling is a procedure used,inadequate shuffles%2C many casinos employ automatic shuffling machines
-
AC代码
#include <iostream> #include <cstdio> using namespace std; const int N = 54; //牌的编号 char mp[5] = {'S','H','C','D','J'}; //牌的编号与花色的映射 int start[N+1]; //初始牌号顺序 int then[N+1]; //换位后牌号顺序 int pos[N+1]; //start[]中每个位置上的牌在操作后应该放在then[]中的位置 int main() { int k; //洗牌次数 cin >> k; for(int i = 1; i <= N; i++) start[i] = i; //初始化牌的编号 for(int i = 1; i <= N; i++) cin >> pos[i]; //指定的洗牌顺序 for( int i = 1 ; i <= k ; i++) //k次循环 { for(int j = 1; j <= N; j++) { then[pos[j]] = start[j]; //关键语句 } for(int j = 1; j <= N; j++) { start[j] = then[j]; //then[]赋值给start[],供下次操作 } } for(int i = 1; i <= N; i++) { if(i-1) cout <<" "; printf("%c%d",mp[(start[i]-1)/13],(start[i]-1)%13 + 1); //关键语句2 //1~13 mp[0] //14~26 mp[1] //... } return 0; }
【PAT A1046】Shortest Distance
-
题目链接
-
分析 : 画一个圆很快就能分析出来
最短距离就两种情况 一个是顺时针的路径 一个是逆时针的路径
-
AC代码
做的太慢了… 做了20min
#include <iostream> #include <algorithm> using namespace std; int N,M; const int n = 100010; int D[n]; int main() { cin >> N; int t1, t2; //两个点 int tt1, tt2; //希望tt1比tt2小,那样子好写代码 int d1 , d2; //d1是顺时针的距离 , d2是逆时针的距离 int sum = 0;// d1 + d2 = 圆的周长 sum int result; //d1 d2中的小的那个 for(int i = 1; i <= N; i++) { cin >> D[i]; sum += D[i]; } cin >> M; for(int i = 1; i <= M; i++) { d1 = 0; d2 = 0; cin >> t1 >> t2; // 输入两个点 tt1 = min(t1,t2); tt2 = max(t1,t2); for(int j = tt1; j <= tt2 - 1; j ++) { d1 += D[j]; } d2 = sum - d1; result = min(d1,d2); cout << result << endl; } return 0; }
【PAT A1065】A+B and C(64bit)
-
题目链接
-
错误代码
-
long long C++ cin
#include <iostream> #include <cstdint> using namespace std; int main() { int T; cin >> T; long long A, B, C; for(int i = 1; i <= T; i++) { cin >> A >> B >> C; if( A + B > C) { cout << "Case #" << i << ": true" << endl; } else { cout << "Case #" << i << ": false" << endl; } } return 0; }
-
-
_int64 C++ cin
emmm按理说已经包含头文件了
#include <iostream> #include <cstdint> using namespace std; int main() { int T; cin >> T; _int64 A, B, C; for(int i = 1; i <= T; i++) { cin >> A >> B >> C; if( A + B > C) { cout << "Case #" << i << ": true" << endl; } else { cout << "Case #" << i << ": false" << endl; } } return 0; }
-
__int64_t 和 u_int64_t cin
都是部分正确
u是unsigned无符号
-
__int128_t C++ cin
cin 处理不了这么大的数
-
AC代码
问了大佬,大佬推荐我直接把位数拓宽
-
用64位,考虑溢出
参考的知乎博主
【PAT A1065】A+B and C(64bit) - Chilan Yuk的文章 - 知乎 https://zhuanlan.zhihu.com/p/399590503
考虑溢出
C一个数本身肯定在范围内
A+B的范围就可能出问题了
A+B可能正正负溢出 也可能负负正溢出
#include <cstdio> #include <iostream> #include <cstdint> using namespace std; int main() { int T; cin >> T; long long int A, B, C, res; for(int i=1;i<=T;++i){ scanf("%lld%lld%lld", &A, &B, &C); res = A + B; if(A > 0 && B > 0 && res < 0) printf("Case #%d: true\n", i); else if(A < 0 && B < 0 && res >= 0) printf("Case #%d: false\n", i); else if(res>C) printf("Case #%d: true\n", i); else printf("Case #%d: false\n", i); } return 0; }
-
-
直接拓宽到128位
-
大佬给的两个输入输出模板
-
输入
inline int read(){ int s = 0, w = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') w = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); } return s * w; }
-
输出
void print(__int128 x) { if(x < 0) { putchar('-'); x = -x; } if(x > 9) print(x / 10); putchar(x % 10 + '0'); }
-
-
AC代码
#include <cstdio> #include <iostream> #include <cstdint> using namespace std; inline __int128_t read(){ __int128_t s = 0, w = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') w = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); } return s * w; } int main() { int T; cin >> T; __int128_t A, B, C, res; for(int i=1;i<=T;++i){ A = read(); B = read(); C = read(); res = A + B; if(A > 0 && B > 0 && res < 0) printf("Case #%d: true\n", i); else if(A < 0 && B < 0 && res >= 0) printf("Case #%d: false\n", i); else if(res>C) printf("Case #%d: true\n", i); else printf("Case #%d: false\n", i); } return 0; }
-
【PAT B1010】一元多项式求导
-
题目链接
-
错误代码
应该是漏了几种情况
题意也理解错了
这里是让你用"0 0"输出 而不是不输出…(直接Continue了可还彳亍)
#include <iostream> using namespace std; int main() { int a; //系数 int n; //指数 while(scanf("%d%d",&a,&n)!=EOF) { if( n == 0 || a == 0) { continue; } else { printf("%d ",a * n); printf("%d ", n - 1); } // if( a == 0 && n == 0) // { // printf("0 "); // printf("0 "); // } } }
-
参考一篇博客之后AC的代码
- https://whenever5225.github.io/2019/08/15/pat1010/
但是这个题解里面写的break我持保留意见,因为题目没说不能有负指数…
看完这个有点启发
还有就是题目里面是以指数递降的方式输入的,这样子就方便控制输出格式了
审题! 题目里面写了非零项系数,那么a肯定不会是0…
所以突然悟了…
#include <iostream> using namespace std; int main() { int a; //系数 int n; //指数 int flag = 0; //识别第一项 while(scanf("%d%d",&a,&n)!=EOF) { //如果多项式的第一项指数为0,求导后即为"零多项式",则应输出0 0 if( n == 0 && flag == 0) { cout <<"0 0"; break; } //如果第一项的指数不为0,则后面指数为0的项不必输出(艹,这是从题目用例得到的隐含条件???) else if(flag == 0) { if( n != 0) { cout << a * n << " " << n - 1; flag = 1; } else { continue; } } else { if( n != 0 ) { cout << " " << a * n << " " << n - 1; } } } return 0; }
-
参考知乎博主
写的很简洁 值得学习
#include <iostream> using namespace std; int main() { int a; //系数 int n; //指数 int flag = 0; //识别第一项 while( cin >> a >> n) { if(n) { if(flag) cout << " "; cout << a * n << " " << n - 1; flag = 1; } } if(!flag) cout << "0 0"; return 0; }
几行代码 还挺妙的
第一项指数为0的情况,因为输入结束了(看来这题真的默认指数都≥0…,不然这样写代码不行…)
然后进入!flag 输出"0 0"
上面格式控制也很巧妙,第一项先"%d %d" 后面的项都是先输出一个空格,再"%d %d"
【PAT A1002】A+B for Polynomials
-
题目链接
-
一步一步 AC
-
初始思路
#include <iostream> using namespace std; int A1[12]; //对应于K1的系数数组 int E1[12]; //对应于K1的指数数组 int A2[12]; //对应于K2的系数数组 int E2[12]; //对应于K2的指数数组 int A3[12]; //合并后的系数数组 int E3[12]; //合并后的指数数组 int main() { int int K1; int K2; cin >> K1; for(int i = 1; i <= K1; i++) { cin >> E1[i] >> A1[i]; } cin >> K2; for(int i = 1; i <= K2; i++) { cin >> E2[i] >> A2[i]; } //下面的问题主要是如何合并数组 //不用动脑的方法是 直接把上面的数组扩充到1000,系数对应多少就是多少,不过其他要初始化为负数,与0区分开 //另一种办法是双指针??? 数据结构那里这个情景似曾相识,但是忘记了啊啊啊 // if(E1[1] >= E1) }
-
感觉好像还是不用动脑的那种好,于是重新写了代码
一顿操作猛如虎,原来只在原地杵
一开始甚至各种double全写的int 下面这个改了改但还是错的七零八落,另外 突然发现忽略了输出用例里面的3?
看样子是项的个数 那还得加个cnt,那输出反而好办了,先输出cnt,好控制了,那还不需要像上题那样设置一个flag 好耶
#include <iostream> using namespace std; double A1[1010]; //对应于K1的系数数组 int E1[1010] = {-1}; //对应于K1的指数数组 double A2[1010]; //对应于K2的系数数组 int E2[1010] = {-1}; //对应于K2的指数数组 double A3[1010]; //合并后的系数数组 int E3[1010] = {-1}; //合并后的指数数组 int main() { int K1; int K2; cin >> K1; int e; double a; for(int i = 1; i <= K1; i++) { cin >> e >> a; E1[e] = e; A1[e] = a; } cin >> K2; for(int i = 1; i <= K2; i++) { cin >> e >> a; E2[e] = e; A2[e] = a; } for(int j = 0; j <= 1000; j ++) { if(E1[j] !=-1 && E2[j] != -1) { E3[j] = E1[j] + E2[j]; A3[j] = A1[j] + A2[j]; } else if(E1[j] == -1 && E2[j] != -1) { E3[j] = E2[j]; A3[j] = A2[j]; } else if(E1[j] != -1 && E2[j] == -1) { E3[j] = E1[j]; A3[j] = A1[j]; } else { E3[j] = -1; } } int flag = 0 ;//判断输出的第一项 for(int j = 1000; j >= 0; j --) { if(E3[j]!=-1) { cout << A3[j] << " " << E3[j] <<" "; } } }
-
加上cnt之后再试了一次
突然意识到可能是初始化的问题,我以为那样子全都赋值为-1了,但是其他的可能初始值都赋值为0了…
-
测试一下 果不其然…
所以要么遍历赋值为-1…
-
感觉悟了 ,还是有错
-
代码
#include <iostream> using namespace std; double A1[1010]; //对应于K1的系数数组 int E1[1010]; //对应于K1的指数数组 double A2[1010]; //对应于K2的系数数组 int E2[1010]; //对应于K2的指数数组 double A3[1010]; //合并后的系数数组 int E3[1010]; //合并后的指数数组 int main() { for(int t = 0; t <= 1009; t++) { E1[t] = -1; E2[t] = -1; } int K1; int K2; cin >> K1; int e; double a; for(int i = 1; i <= K1; i++) { cin >> e >> a; E1[e] = e; A1[e] = a; } cin >> K2; for(int i = 1; i <= K2; i++) { cin >> e >> a; E2[e] = e; A2[e] = a; } int cnt = 0; for(int j = 0; j <= 1000; j ++) { if(E1[j] !=-1 && E2[j] != -1) { E3[j] = E1[j] + E2[j]; A3[j] = A1[j] + A2[j]; cnt ++; } else if(E1[j] == -1 && E2[j] != -1) { E3[j] = E2[j]; A3[j] = A2[j]; cnt ++; } else if(E1[j] != -1 && E2[j] == -1) { E3[j] = E1[j]; A3[j] = A1[j]; cnt ++; } else { E3[j] = -1; } } int flag = 0 ;//判断输出的第一项 cout << cnt; for(int j = 1000; j >= 0; j --) { if(E3[j]!=-1) { cout << " " << E3[j] << " " << A3[j] ; } } }
-
-
拆东墙补西墙???
刚刚那个问题其实出在这里👇
两个指数都不是-1,说明指数相等,那么E3就只要等于其中一个就可以了,而不是等于他们的和
但是代码还是错的…
#include <iostream> using namespace std; double A1[1010]; //对应于K1的系数数组 int E1[1010]; //对应于K1的指数数组 double A2[1010]; //对应于K2的系数数组 int E2[1010]; //对应于K2的指数数组 double A3[1010]; //合并后的系数数组 int E3[1010]; //合并后的指数数组 int main() { for(int t = 0; t <= 1009; t++) { E1[t] = -1; E2[t] = -1; E3[t] = -1; } int K1; int K2; cin >> K1; int e; double a; for(int i = 1; i <= K1; i++) { cin >> e >> a; E1[e] = e; A1[e] = a; } cin >> K2; for(int i = 1; i <= K2; i++) { cin >> e >> a; E2[e] = e; A2[e] = a; } int cnt = 0; for(int j = 0; j <= 1000; j ++) { if(E1[j] !=-1 && E2[j] != -1) { E3[j] = E1[j] ; A3[j] = A1[j] + A2[j]; cnt ++; } else if(E1[j] == -1 && E2[j] != -1) { E3[j] = E2[j]; A3[j] = A2[j]; cnt ++; } else if(E1[j] != -1 && E2[j] == -1) { E3[j] = E1[j]; A3[j] = A1[j]; cnt ++; } else { E3[j] = -1; } } int flag = 0 ;//判断输出的第一项 cout << cnt; for(int j = 1000; j >= 0; j --) { if(E3[j]!=-1) { cout << " " << E3[j] << " " << A3[j] ; } } }
-
再进一步 计数器是非零项的数目… 如果A3是零 不可输出
加了判断
emm
- 代码
#include <iostream> using namespace std; double A1[1010]; //对应于K1的系数数组 int E1[1010]; //对应于K1的指数数组 double A2[1010]; //对应于K2的系数数组 int E2[1010]; //对应于K2的指数数组 double A3[1010]; //合并后的系数数组 int E3[1010]; //合并后的指数数组 int main() { for(int t = 0; t <= 1009; t++) { E1[t] = -1; E2[t] = -1; E3[t] = -1; } int K1; int K2; cin >> K1; int e; double a; for(int i = 1; i <= K1; i++) { cin >> e >> a; E1[e] = e; A1[e] = a; } cin >> K2; for(int i = 1; i <= K2; i++) { cin >> e >> a; E2[e] = e; A2[e] = a; } int cnt = 0; for(int j = 0; j <= 1000; j ++) { if(E1[j] !=-1 && E2[j] != -1) { E3[j] = E1[j] ; A3[j] = A1[j] + A2[j]; if(A3[j]!=0) cnt ++; } else if(E1[j] == -1 && E2[j] != -1) { E3[j] = E2[j]; A3[j] = A2[j]; if(A3[j]!=0) cnt ++; } else if(E1[j] != -1 && E2[j] == -1) { E3[j] = E1[j]; A3[j] = A1[j]; if(A3[j]!=0) cnt ++; } else { E3[j] = -1; } } int flag = 0 ;//判断输出的第一项 cout << cnt; for(int j = 1000; j >= 0; j --) { if(E3[j]!=-1 && A3[j] != 0) { cout << " " << E3[j] << " " << A3[j] ; } } }
-
-
绷不住了,原来还错在了格式上
题目要求保留1位小数!
-
AC代码
#include <iostream> using namespace std; double A1[1010]; //对应于K1的系数数组 int E1[1010]; //对应于K1的指数数组 double A2[1010]; //对应于K2的系数数组 int E2[1010]; //对应于K2的指数数组 double A3[1010]; //合并后的系数数组 int E3[1010]; //合并后的指数数组 int main() { for(int t = 0; t <= 1009; t++) { E1[t] = -1; E2[t] = -1; E3[t] = -1; } int K1; int K2; cin >> K1; int e; double a; for(int i = 1; i <= K1; i++) { cin >> e >> a; E1[e] = e; A1[e] = a; } cin >> K2; for(int i = 1; i <= K2; i++) { cin >> e >> a; E2[e] = e; A2[e] = a; } int cnt = 0; for(int j = 0; j <= 1000; j ++) { if(E1[j] !=-1 && E2[j] != -1) { E3[j] = E1[j] ; A3[j] = A1[j] + A2[j]; if(A3[j]!=0) cnt ++; } else if(E1[j] == -1 && E2[j] != -1) { E3[j] = E2[j]; A3[j] = A2[j]; if(A3[j]!=0) cnt ++; } else if(E1[j] != -1 && E2[j] == -1) { E3[j] = E1[j]; A3[j] = A1[j]; if(A3[j]!=0) cnt ++; } else { E3[j] = -1; } } int flag = 0 ;//判断输出的第一项 cout << cnt; for(int j = 1000; j >= 0; j --) { if(E3[j]!=-1 && A3[j] != 0) { cout << " " << E3[j] << " "; printf("%.1lf", A3[j]); } } }
-
-
学习别人的代码 ,自己写的太麻烦了
突然发现 既然题目不输出系数为0的,然后 前面的E数组也是多余的,因为A数组的下标就是E数组的值…
下面的参考了文末链接给出的那位知乎博主的代码
#include <iostream> using namespace std; int main() { int K1, K2, exp, count = 0; double coef[1005]={0}; double a; cin >> K1; while(K1--) { cin >> exp >> a; coef[exp] += a; } cin >> K2; while(K2--) { cin >> exp >> a; coef[exp] += a; } for(int i = 1000; i >= 0 ; --i) if(coef[i]) count++; cout << count; for(int i = 1000; i >= 0 ; --i) if(coef[i]) printf(" %d %.1f", i ,coef[i]); }
【PAT A1009】Product of Polynomials
-
题目链接
-
AC代码
和上一题差不多 这题需要扩一下数组
另外记得变量初始化
#include <iostream> using namespace std; int main() { int K1,K2; //N1 + N2 <= 2000 指数最大2k double coef1[1010]={0.0}; double coef2[1010]={0.0}; double coef[2010]={0.0}; double a;//系数 int exp; //指数 int cnt = 0; cin >> K1; while(K1--) { cin >> exp >> a; coef1[exp] += a; } cin >> K2; while(K2--) { cin >> exp >> a; coef2[exp] += a; } for(int i = 0; i <= 1000; ++i) { for(int j = 0 ; j <= 1000; ++j) { coef[i+j] += coef1[i]*coef2[j]; } } for(int i = 0; i <= 2000; ++i) { if(coef[i]) ++cnt; } cout << cnt; for(int i = 2000; i >= 0; --i) { if(coef[i]) printf(" %d %.1f",i,coef[i]); } return 0; }
参考资料
- CCF CSP认证从零带你开始刷题(更新中) - Chilan Yuk的文章 - 知乎 https://zhuanlan.zhihu.com/p/401630124