胡凡 《算法笔记》 上机实战训练指南 3.1 简单模拟
创始人
2024-04-27 22:25:37
0

胡凡 《算法笔记》 上机实战训练指南 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 简单模拟

image-20221221120000918

【PAT B1001】害死人不偿命的(3n+1)猜想

  • 题目链接

  • AC代码

    #include 
    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 
    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;
    }
    
  • 上面的代码的漏洞在于,如果第一个学校的总分就是最高的,无法输出

    image-20221221120702393
  • 于是,将自己的代码里面的 residx初始化为1,但还是有数据点没通过

    image-20221221120843907
    • 去参考了这个:【PAT B1032】挖掘机技术哪家强 - Chilan Yuk的文章 - 知乎 https://zhuanlan.zhihu.com/p/397334909
  • 看了半天,不知道为啥错,仔细一看,数组开小了…

    • 10的5次方… 就开了个10010… 蚌埠住了… 这里浪费了一堆时间
  • AC代码

    #include 
    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 
    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 
    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 #"<

【PAT B1016】部分A+B

  • 题目链接

  • AC代码

    #include 
    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 <

【PAT B1026】程序运行时间

  • 题目链接

  • 思路比较顺畅,但是一开始的答案格式错了,时分秒的输出要保证不足两位时高位用0 补充

    • 错误格式代码

      #include 
      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 
      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 
    #include 
    #include 
    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 
    #include 
    #include 
    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 
    #include 
    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<

    想到引用不错,但还是感觉自己写的有点复杂

  • 书上答案👇比较简洁

    #include 
    #include 
    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 
    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 
    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 
    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 
    #include 
    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;
    }
    
    image-20221221130425799

    在这之前还犯了一个窒息的错误

    循环输入数组的时候,循环体里面的语句写成了 cin >> num[1]

    在这种时候,最好借助cout来检查一下,果真,

    一开始遍历输出就发现不对劲

    在这里插入图片描述

  • 浅看了一下答案,发现对第五个是否有数字都进行了判断…于是加上去了

    在这里插入图片描述

    结果果真多过了几个测试样例

    image-20221221130547259
  • 发现错误后AC了,难蚌

    在这里插入图片描述

    这里为啥除以3.0???… 应该最后的和除以cnt[4]呀!!!

    估计是因为看到题目里面写的余3…所以想当然的写成了除以3.0… 然后和高中一样 经常犯这种错误😅

    还有一开始怀疑cnt[5]的作用…

    如果没有除5余4 的数的话,就是0…

    AC代码如下

    #include 
    #include 
    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 
    #include 
    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<= AR[1] && AR[0] >= )int maxBele = *max_element(BR,BR+3);if(BR[2]==maxBele)cout<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 
    #include 
    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

  • 题目链接

  • 分析 : 画一个圆很快就能分析出来

    img

    最短距离就两种情况 一个是顺时针的路径 一个是逆时针的路径

  • AC代码

    做的太慢了… 做了20min

    #include 
    #include 
    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 = 圆的周长 sumint 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

      image-20221221131405948

      #include 
      #include 
      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

    image-20221221131951116

    emmm按理说已经包含头文件了

    #include 
    #include 
    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 
      #include 
      #include 
      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 
      #include 
      #include 
      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了可还彳亍)

    img
    #include 
    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…

    所以突然悟了…

    image-20221221132356367 image-20221221132408553

    #include 
    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 
    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 
      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 
      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 
        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] ;}}}
        
        image-20221221132951269
    • 拆东墙补西墙???

      刚刚那个问题其实出在这里👇

      image-20221221133022497

      两个指数都不是-1,说明指数相等,那么E3就只要等于其中一个就可以了,而不是等于他们的和

      但是代码还是错的…

      #include 
      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] ;}}}
      
      image-20221221133045028
    • 再进一步 计数器是非零项的数目… 如果A3是零 不可输出

      加了判断

      image-20221221133119375 image-20221221133127488

      emm

      • 代码
      #include 
      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 
      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]);}}}
      

      image-20221221133306261

  • 学习别人的代码 ,自己写的太麻烦了

    突然发现 既然题目不输出系数为0的,然后 前面的E数组也是多余的,因为A数组的下标就是E数组的值…

    下面的参考了文末链接给出的那位知乎博主的代码

    #include 
    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 
    using namespace std;
    int main()
    {int K1,K2;//N1 + N2 <= 2000 指数最大2kdouble 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

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...