NOJ C++ G3:enum 记录

  • 3.1

    image-20230411210203587

    1
    2
    3
    4
    5
    6
    for(int i = 0; i < t; i++){
    int temp = alpha;
    alpha = beta;
    beta = 3* temp + 2* beta;
    }
    //两个变量都需要依赖对方的初始值变化时,加上temp

    3.2

    image-20230411210511840

    这题枚举不是很好想,用递归会简单一些

    1
    2
    3
    4
    5
    6
    7
    int measures(int n){
    if(n < 3) return 0;
    if(n == 3) return 1;
    if(n == 4) return 3;
    return 2*measures(n-1) + pow(2,n-4) - measures(n-4);
    }
    //本身没有太多要注意的,pow函数接受传入时会自动转化为小数,注意有些题里的精度问题

    3.3

    image-20230411210927571

    • 循环时:对于只需单次满足判断结果的情况要break
    • 嵌套循环中要使用上层循环变量,且上层变量不应改变时,用temp

    3.4

    image-20230411211552157

    • 数据陷阱:1.0/(i*i)会出现精度问题,原因是直接计算 i*i 会溢出或者太小,应该用(1.0/i)*(1.0/i)
    • 保留小数时注意用fixed,保留有效数字时不用加

    3.5

    image-20230411211927458

    • 数据陷阱:分数太小时double的精度不够
    • 解决方法:模拟手算,不断除余数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int main(){
    int a, b, c;
    cin >> a >> b >> c;
    cout << a/b << '.';
    for(int i=0; i<c; i++){
    a = a%b*10;
    cout << a/b;
    }
    }

    3.6

    image-20230411212217181

    • 新:用STLnext_permutation(a,a+n),要包括<algorithm>的头文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int main(){
    int nums[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    do{
    int a = nums[0]*100 + nums[1]*10 + nums[2];
    int b = nums[3]*100 + nums[4]*10 + nums[5];
    int c = nums[6]*100 + nums[7]*10 + nums[8];
    if(a*2 == b && a*3 == c){
    cout << a << ' ' << b << ' ' << c << endl;
    }
    }
    while(next_permutation(nums, nums+9));
    return 0;
    }

    3.7

    image-20230411212418465

    • 注意有些固定算子在每次循环前或后要重新赋为初始值,比如获得多个sumprod
    • 思考方式:要多用封装好的函数,减少底层逻辑思考,直接思考框架,如此题在遍历中用max,省去if
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    #include <iostream>
    using namespace std;

    int main(){
    int n, prod=1, ans;
    cin >> n;
    int S[n], max1[n];
    for(int i=0; i<n; i++){
    cin >> S[i];
    }
    /*方法一:定义记录某元素为起始的所有连续子列乘积最大值的数组,再依次比较最大值
    for(int i=0; i<n; i++){
    max1[i] = S[i]; //初始化max1[i]
    for(int j=i; j<n; j++){
    prod *= S[j]; //得到i开头的所有的连续子列乘积
    max1[i] = max(max1[i], prod); //不断更新max1[i]
    }
    prod = 1; //每次都要重新赋值为1
    }*/

    //方法二:换算法,考虑到负数,记录以某元素结尾的子列的最大乘积和最小乘积
    //并不断比较得出新的最大积和最小积,新的最大积和最小积由5个可能的值通过max/min产生
    //省去了正负的判断,全用max代替,代码更简洁
    //同时可应对变式:非连续子列的最大积
    int maxProd = S[0], minProd = S[0], ans = S[0];
    for(int i=1; i<n; i++){
    int a = S[i] * maxProd, b = S[i] * minProd;
    maxProd = max(S[i], max(a, b));
    //变式:maxProd = max(max(max(S[i], max(a, b)),maxProd),minProd);
    minProd = min(S[i], min(a, b));
    //变式:minProd = min(min(min(S[i], min(a, b)),maxProd),minProd);
    ans = max(ans, maxProd);
    }
    if(ans > 0) cout << ans;
    else cout << -1;
    return 0;
    }

    3.8

    image-20230411213326869

    • 英文:分子numerator,分母:denominator
    • 循环多且相互联系时,要注意彼此的边界,最好在写之前确定

    3.9

    image-20230411213753211

    • 注意一下条件为<=for循环结束时i的值为最大值+1

    3.10

    • 没啥好说的(^▽^)