OJ刷题笔记(基础20-40)

本文记录了在在线判题平台OJ上的刷题笔记,涉及时间转换、集合运算、瓷砖铺放、字符串对比等多个算法问题的解题思路。通过分析题目,讲解了如何利用数学、STL容器、递归、动态规划等方法解决问题,提供了实用的编程技巧,如浮点数占位符、字符串处理和矩阵乘法等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

TsinSen清橙:

  1. 缩小的陆地(shrinking land)

    解题思路:侵蚀面积s每年增加50,当s大于由原点为圆心、房子到原点的长度为半径的圆的面积一半时,房子将受到侵蚀,增加的50的次数即第几年。

    • PI的精度至少要取到3.1416,PI = 4 * atan(1.0) = 3.14159;
    • printf("%.0f",z);scanf("%f %f",&x,y&); scanf("%1f %1f",&x,&y) ; //浮点数占位符,取整输出占位符。
    • 使用cin cout可以忽略输入输出数据的占位符;printf("%d ",a)可以输出空格。
    #include <iostream>
    #include <cmath>
    using namespace std;
    int main(){
        float s,x,y;
        int t,z;
        cin >> t;
        while(t--){
            z = 0;
           cin >> x >> y;
            s = ( x * x + y * y ) * 3.14159/ 2;
            while(z*50 <= s){
                z++;
            }
            cout<<z<<endl;
        }
    	return 0;
    }	
    
  2. 集合运算

    解题思路:利用list的merge() / sort() / unique() 函数快速求并集;并集中B中没有的是B在A中的差集,放入差集集合;AB中同时有的元素,放入交集集合。

    • 新建数组:int A[n ] ;
    • stl的list新建list < int > A;A.sort(); A.merge(B); A.push_back(); A.front();A.pop_front();
  3. 时间转换

    解题思路:逐层减去,即先用总时间T0/3600向下取整,是H;减去小时时间H,更新总时间T1/60是分钟时间M,减去分钟时间,是最后的秒时间S;

    • #include<math.h> 对除法结果用floor(number),向下取整。
  4. 瓷砖铺放

    解题思路:可以使用斐波那契数列(递归)、动态规划(递推)两种方法 来解。

    • 递归:if(n>1) return pave(n-2) + pave(n-1);
    • 递推:for (int i=2;i<=n;++i)a[i]=a[i-1]+a[i-2];
    • 瓷砖铺放再讨论问题??
  5. 字符串对比

    解题思路:长度不同返回1;长度相同且相等,返回2;长度相同且统一变小写后相同,返回3;否则返回4。

    • printf输出字符串用法:printf(“%s” , s**.c_str()**); //string中c_str()成员方法返回当前字符串的首字符地址
    • scanf接收字符串:scanf("%s" , **&**strname);
    • 字符串的输入输出,使用cin 、cout比较方便;
    • str1.compare(str2)函数比较是否相同时,不区分大小写;需要区分大小写比较时,可以采用数组遍历方式,逐个比较(单个字符用“==”判断相同)。
    • 输出多个空格:printf("%*s","")。
  6. 字符统计

    解题思路:开一个长度为26的数组,数组内全部初始化为0;扫描字符串,将小写字母映射为数组的下标,出现的字符,在对应的数组上会+1;在顺序输出数组非空元素。

    • 新建数组初始化为0:int a[26] = { };或int a [26] = {0};
    • 数字与字符的转化:(1)字母转数字:int(字母),例如int(a)或a+0 ;(2)数字转字母:char(数字),数字对应assii表的数值,例如char(97)。
  7. 拼写检查

    解题思路:(1)要先判断相等的情况,用str.compare(str1)直接输出;(2)再判断长度相等但错写1个的情况,检查长度,逐个比较不一致的个数,如果只有1个,就是这种错写的情况;(3)在考虑多写1个或漏写1个,前半段相同,跳过当前不一致的单词后,如果其余都相同,则属于这种相似;(4)最后前述匹配均失败,则是noanswer。

    • 字符串相等的判断结果:str.compare(str1)如果相同会返回0;
  8. 选择计算

    解题思路:分支选择

    • 求最大公约数:较小者减,找到能同时取余为0的第一个数。
    • 求最小公倍数:即x*y/两者的最大公约数。
  9. 补写函数

    解题思路:第一个函数要用指针变量找最值;第二个函数是普通变量找最值。

  10. 球队排名

    解题思路:按照得分、胜场数、进球数排序。

    • [ ]
  11. 画20行以内三角形

    思路:图形规律是第i行起始字母是字母表第i个,总共打印(2*i+1)个字母,左右对称即左边i个,右边i个,中间是A。解法上,构造一个二维数组,将数组填充大写字母,填充时,对称用abs(i-j)实现。

    • #include,使用abs()函数要先引用cmath。

      #include<iostream>
      #include<cmath>
      using namespace std;
      
      int main()
      {
          int n;
          //cin>>n;
          n = 15;
          char chars[n][n*2-1];
          for(int i=0;i<n;++i){
              for(int j = 0;j<2*i+1;++j){
                  chars[i][j] = char(65+abs(i-j));
              }
          }
          for(int i=0;i<n;++i){
              for(int j = 0;j<2*i+1;++j){
                  cout<<chars[i][j];
              }
              cout<<endl;
          }
          return 0;
      }
      
  12. 绘制图形

  13. 孪生素数对

    差值为2的两个素数,为孪生素数:写一个判断是不是素数的函数,然后从a到b,逐个检查i和i+2是不是素数,如果是就输出。
    判别素数:一个数,如果有因子,那么在它的平方根数以内就应该有,否则就没有因子。故判断m是否为素数,只要试除到m的平方根就可以了。

    #include<iostream>
    using namespace std;
    
    int isPrime(int n)
    {
        for(int i = 2;i*i<=n;++i){
            if(n%i == 0)
                return 0;
        }
        return 1;
    }
    
    int main()
    {
        int a,b;
        bool hasPrime = false;
        cin>>a>>b;
        for(int i = a;i <= b-2;++i){
            if(isPrime(i) && isPrime(i+2)){
                hasPrime = true;
                cout<<i<<' '<<i+2<<endl;//i+2<=b
            }
        }
        if(hasPrime == false){
            cout<<-1<<endl;
        }
        return 0;
    }	
    
  14. 素数之和

    判断区间的素数,并求和

    #include<stdio.h>
    using namespace std;
    
    int isPrime(int x){
        for(int i = 2;i*i <= x;++i){
            if(x%i==0)
                return 0;
        }
        return 1;
    }
    
    int main()
    {
        int n=1;
        while(n != 0){
            scanf("%d",&n);
            int sum = 0;
            for(int i = 2;i<=n;++i ){
                if(isPrime(i))
                    sum += i;
            }
            if(n!=0)
                printf("%d\n",sum);//等于0是直接退出,不输出任何符号
        }
        return 0;
    }
    
  15. A1036. 分解质因数

    遇到的每个数,本身是质数,则输出本身;如果不是质数,就对比它小的质数取模,能整数的,得道第一个数;再对剩下的数如此判断。得道的质因数用什么存储?

    #include<stdio.h>
    using namespace std;
    
    int main()
    {
        int a,b,i,j,k;
        scanf("%d %d",&a,&b);
        for(i = a;i <= b;++i){
            printf("%d=",i);
            j = i;
            for(k = 2;k<=j;++k){
                while(k!=j){
                    if(j%k==0){
                        printf("%d*",k);
                        j = j/k;
                    }else break;
                }
            }
            printf("%d\n",j);
        }
    
        return 0;
    }
    
  16. A1037. 下楼问题

    用递归的方式,找到h=0和h=1、h<0的递归基。另外,测试点h可能有4-20范围之外的取值。

    #include<iostream>
    using namespace std;
    
    int steps(int n)
    {
        if(n < 0)
            return 0;
        if(n == 0 || n == 1)
            return 1;
        return steps(n-1) + steps(n-2) + steps(n-3);
    }
    
    int main()
    {
        int h,ans=0;
        cin>>h;
        if(h<4 || h>20)
            cout<<0;
        else
            cout<<steps(h);
        return 0;
    }
    
  17. A1038. 超级重复串

    截取字符串的子串,比较相等,逐渐扩大串长度。

    #include<iostream>
    #include<string>
    using namespace std;
    
    int main()
    {
        string a;
        cin>>a;
        int len =a.length();
        int max_len = 0;
    
        for(int i = 0;i<len;++i){
            for(int j = max_len;j<len+1;j+=2){
                if(i+j>len) break;
                string s1 = a.substr(i,j/2);
                string s2 = a.substr(i+j/2,j/2);
                if(s1 == s2) max_len = j;
            }
        }
        cout<<max_len<<endl;
    }
    
  18. 欢乐的跳跃着

    数列两项之差,为自然数。

    #include<iostream>
    #include<cmath>
    #include<list>
    using namespace std;
    
    int main()
    {
        int n,x;
        bool flag = false;
        cin>>n;
    
        int a_arr[n];
        list<int>  b_arr;
        for(int i = 0;i<n;++i){
            cin>>x;
            a_arr[i] = x;
        }
        for(int j = 0;j <= n-1;++j){
            b_arr.push_back(abs(a_arr[j]- a_arr[j+1]));
        }
    
        b_arr.sort();
        for(int k = 1;k <= n-1;++k){
            if(b_arr.front() != k){
                flag = true;
                cout<<"I'm unhappy!!"<<endl;
            }
            b_arr.pop_front();
        }
        if(flag == false){
            cout<<"I'm happy!!"<<endl;
        }
        return 0;
    }
    
  19. cantor表

    以分数形式输出第n项:需要找到分子、分母,斜着右侧往上看(状二叉树),n对不大于n的最大自然数列和(对应所在行 i )求余数 j(对应所在行的位置)。通过分析Z字形的走势,可知,若行序 i 为偶数,则 j 应从右向左计数,反之 i为奇数,j从左侧开始计数,分子分母分别向相反方向单调。

  20. == 矩阵乘法==

    构造两个N阶矩阵A[n][n]和B[n][n],A用于存放幂次的结果,矩阵的乘法之后更新A。好在m不大于5,每次都可以循环计算,数据量还不算太大。

在这里插入代码片
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值