PAT-数学(AcWingPAT甲级课笔记)

目录

1049 Counting Ones

1059 Prime Factors 

1081 Rational Sum

1088 Rational Arithmetic

1096 Consecutive Factors

1103 Integer Factorization

1104 Sum of Number Segments


1049 Counting Ones

解析

小学奥数题

枚举每一位上为1的数的个数,对每一位进行分情况讨论。

假设N可以表示成abcdefg,其中每一位代表一个0-9的数字,假如当前枚举到了从大到小的第4为,即d所在的数位,我们对d进行分情况讨论:

1. d < 1:则前3位可以选择0 ~ abc - 1 后3位可以选择 0 ~ 999
2. d = 1:
        前3位可以选择0 ~ abc - 1 后3位可以选择0~999
        前3位可以选择abc 后3位可以选择0 ~ efg
3. d > 1:前3位可以选择0 ~ abc 后3位可以选择0-999
可以看到,枚举每一位时用到的数有abc, efg 以及10的k次方(k为从小到大的位数),在每次循环内部先将该三个变量预处理,在累加结果时方便直接调用

注意点

#include <iostream>
#include <vector>

using namespace std;

int calc(int n){
    vector<int> nums;
    while (n) nums.push_back(n % 10), n /= 10;

    int res = 0;  //存答案 
    for (int i = nums.size() - 1; i >= 0; i -- ){
        int d = nums[i];  //第d位
        int left = 0, right = 0, power = 1;  //left:d左边的值, right:d右边。 power:多少次方
        for (int j = nums.size() - 1; j > i; j -- ) left = left * 10 + nums[j];
        for (int j = i - 1; j >= 0; j -- ){
            right = right * 10 + nums[j];
            power *= 10;
        }

        if (d == 0) res += left * power;   //分3种情况讨论
        else if (d == 1) res += left * power + right + 1;
        else res += (left + 1) * power;
    }

    return res;
}

int main(){
    int n;
    cin >> n;

    cout << calc(n) << endl;

    return 0;
}

1059 Prime Factors 

解析

注意点

不用先把质数筛选出来,可以直接从2开始遍历每一个数,如试2, 3,试4的时候,4不是质数,4必然有小于它的质因子, 这些质因子之前已经被筛完了,所以一定不会被4整除。可以理解为,不是质数会直接跳过。

质数:条件写成i <= n / i,写成 i * i <= n 有的题会错

#include <iostream>

using namespace std;

int main(){
    int n; 
    cin >> n;

    printf("%d=", n);
    if (n == 1) puts("1");
    else{
        bool is_first = true;
        for (int i = 2; i <= n / i; i ++ )
            if (n % i == 0){
                int k = 0;
                while (n % i == 0) n /= i, k ++ ;

                if (!is_first) cout << '*';
                else is_first = false;

                cout << i;
                if (k > 1) cout << "^" << k;
            }

        if (n > 1){
            if (!is_first) cout << '*';
            cout << n;
        }
    }

    return 0;
}

1081 Rational Sum

单词:

numerator 分子 

denominator 分母

解析

分数的运算

注意点

根据题目给的边界数据来考虑。

只有1,2个点没过,一般是数组越界或整数溢出

#include <iostream>

using namespace std;

typedef long long LL;

//辗转相除法模板,找最大公约数
LL gcd(LL a, LL b){
    return b ? gcd(b, a % b) : a;
}

int main(){
    LL a = 0, b = 1;  //a存分子的和, b存分母的和

    int n;
    cin >> n;
    for (int i = 0; i < n; i ++ ){
        LL c, d;
        scanf("%lld/%lld", &c, &d);

        LL t = gcd(c, d);
        c /= t, d /= t;

        t = gcd(b, d);    //通分的时候,分母通分成最小公倍数
        a = d / t * a + b / t * c;
        b = b / t * d;

        t = gcd(a, b); //多约分,以免超出数据范围
        a /= t, b /= t;
    }

    if (b == 1) cout << a;
    else{ 
        if (a >= b) printf("%lld ", a / b), a %= b;
        printf("%lld/%lld", a, b);
    }

    return 0;
}

1088 Rational Arithmetic

解析

分数的运算,简单模拟就行

输出比较麻烦

注意点

数据比较小,不用经常约分

#include <iostream>

using namespace std;

typedef long long LL;

LL gcd(LL a, LL b){   //求最大公约数
    return b ? gcd(b, a % b) : a;
}

void print(LL a, LL b){
    LL d = gcd(a, b);
    a /= d, b /= d;

    if (b < 0) a *= -1, b *= -1;
    bool is_minus = a < 0;

    if (is_minus) cout << "(";

    if (b == 1) cout << a;
    else{
        if (abs(a) >= b) printf("%lld ", a / b), a = abs(a) % b;
        printf("%lld/%lld", a, b);
    }

    if (is_minus) cout << ")";
}

void add(LL a, LL b, LL c, LL d){
    print(a, b), cout << " + ", print(c, d), cout << " = ";
    a = a * d + b * c;
    b = b * d;
    print(a, b), cout << endl;
}

void sub(LL a, LL b, LL c, LL d){
    print(a, b), cout << " - ", print(c, d), cout << " = ";
    a = a * d - b * c;
    b = b * d;
    print(a, b), cout << endl;
}

void mul(LL a, LL b, LL c, LL d){
    print(a, b), cout << " * ", print(c, d), cout << " = ";
    a = a * c;
    b = b * d;
    print(a, b), cout << endl;
}

void div(LL a, LL b, LL c, LL d){
    print(a, b), cout << " / ", print(c, d), cout << " = ";
    if (!c) puts("Inf");
    else{
        a = a * d;
        b = b * c;
        print(a, b), cout << endl;
    }
}

int main(){
    LL a, b, c, d;
    scanf("%lld/%lld %lld/%lld", &a, &b, &c, &d);

    add(a, b, c, d);
    sub(a, b, c, d);
    mul(a, b, c, d);
    div(a, b, c, d);

    return 0;
}

1096 Consecutive Factors

解析

1.枚举起始位置 k

2.枚举长度

注意点

#include <iostream>
#include <vector>

using namespace std;

int main(){
    int n;
    cin >> n;

    vector<int> res;
    for (int i = 2; i <= n / i; i ++ )
        if (n % i == 0){
            vector<int> seq;
            for (int m = n, j = i; m % j == 0; j ++ ){
                seq.push_back(j);
                m /= j;
            }

            if (seq.size() > res.size()) res = seq;
        }

    if (res.empty()) res.push_back(n);

    cout << res.size() << endl;
    cout << res[0];
    for (int i = 1; i < res.size(); i ++ ) cout << '*' << res[i];

    return 0;
}

1103 Integer Factorization

解析

注意点

1104 Sum of Number Segments

解析

注意点

#include <iostream>

using namespace std;

int main(){
    int n;
    cin >> n;
    long double res = 0;
    for (int i = 1; i <= n; i ++ ){
        long double x;
        cin >> x;

        res += x * i * (n - i + 1);
    }

    printf("%.2Lf", res);

    return 0;
}

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值