胡凡 《算法笔记》 上机实战训练指南 3.1 简单模拟

胡凡 《算法笔记》 上机实战训练指南 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;
    }
    
  • 上面的代码的漏洞在于,如果第一个学校的总分就是最高的,无法输出

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

    • 去参考了这个:【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 #"<<i<<": true"<<endl;
            else
                cout<<"Case #"<<i<<": false"<<endl;
            i+=1;
        }
        return 0;
    }
    

【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 <<endl;
        return 0;
    }
    

【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<<jf<<" "<<yf;
        return 0;
    }
    

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

  • 书上答案比较简洁

    #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;
    }
    

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

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

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

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

    胡凡 《算法笔记》 上机实战训练指南 3.1 简单模拟_第1张图片

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

    在这里插入图片描述

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

  • 发现错误后AC了,难蚌

    胡凡 《算法笔记》 上机实战训练指南 3.1 简单模拟_第2张图片

    这里为啥除以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<<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 
    #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

  • 题目链接

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

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

  • 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 = 圆的周长 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 
      #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了可还彳亍)

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

    所以突然悟了…

    #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

    • 初始思路

      胡凡 《算法笔记》 上机实战训练指南 3.1 简单模拟_第3张图片

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

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

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

      加了判断

      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]);
               }
           }
          
      }
      

      胡凡 《算法笔记》 上机实战训练指南 3.1 简单模拟_第4张图片

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

    突然发现 既然题目不输出系数为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 指数最大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

你可能感兴趣的:(数据结构与算法,算法,c++)