模拟笔试:卡码网2023年快手笔试真题

1.158同余方程

思路

纯数学的思路,想不出来的话很难做。

欧几里得算法视频讲解

代码

#include <iostream>
using namespace std;

// 扩展欧几里得:计算 ax + by = gcd(a, b) 的解
long long extended_gcd(long long a, long long b, long long &x, long long &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    long long x1, y1;
    long long gcd = extended_gcd(b, a % b, x1, y1);
    x = y1;
    y = x1 - (a / b) * y1;
    return gcd;
}

int main() {
    long long a, b;
    cin >> a >> b;

    long long x, y;
    long long gcd = extended_gcd(a, b, x, y);

    // 由于我们只需要模 b 的正整数解,所以我们要保证 x 是正数
    x = (x % b + b) % b;

    cout << x << endl;

    return 0;
}

2.159大整数乘法

思路

从低到高按位相乘进位累加。

具体实现

1.先对其进行输入,分配给s1和s2分别代表两个大数,长度分别为n1和n2

2.由简单的数学知识可得n1*n2的数相乘的范围在(n1+n2-1,n1+n2),所以生成一个n1+n2全为'0'的字符串来存放相乘后的结果。

3.遍历,从右到左进行遍历(在代码中为了统一,我使用的是从左到右遍历,i,j,k分别代表与对应的最右端的距离来实现从右到左)

注意事项:这个里面只遍历n1+n2-1位,最高位是不进行遍历的,而是最后根据进位来进行计算的。

4遍历的内部逻辑:i,j分别代表相应的位数,根据数学知识可以知道(百位 = 百位*个位 + 十位*十位 + 个位*百位),所以第k位的值我们可以从s1[i]和s2[j]相乘获取。在这个里面,0代表个位,1代表十位等。所以k  = i + j;

add表示进位,sum代表相应的累加和。得到乘法的结果之类,根据累加和得到对应的进位,然后sum只保留个位作为最后的当前位的值。

注意事项:要将'0'变成0才能参与相乘。先更新进位再更新累加和。

5.每次遍历前需要将sum = sum +add来获取当前位的累加值。同时将add = 0表示遍历前的进位为0,在遍历结束之后将sum = 0。

6.对最高位的处理,根据前面的进位来得到最高位,同时如果最高位最后的结果为0的话,要删除。

代码

#include<iostream>
#include<string>
using namespace std;
int main(){
    string s,s1,s2;
    getline(cin,s);
    int i = 0;
    int j = 0;
    int n = s.size();
    for(;i<n;i++){
        if(s[i] == ' '){
            s1 = s.substr(0,i);
            break;
        }
    }
    int n1 = i;//代表两个的长度
    int n2 = n-i-1;
    s2 = s.substr(i+1,n - i - 1);//获得对应的两个数
    //cout<<n1<<" "<<n2<<endl;
    string ret = string(n-1,'0');//最长的长度为这个,后序把0给消掉
    int add = 0;//代表的是进位
    int sum = 0;//代表的是累加和
    for(int k = 0;k<n-2;k++){//最高位是不参与计算的,直接算最后的进位即可
        sum = sum + add;//前面的进位
        add = 0;//此时计算的就是当前位的进位了
        for(i = 0;i<n1&&i<=k;i++){//满足两个情况1:长度在这个之内,2,位数要满足
            j = k - i;//代表s2对应的位数
            if(j>=n2){
                continue;
            }
            int multi = (s1[n1-1-i]-'0')*(s2[n2-1-j]-'0');
            //cout<<multi<<endl;
            sum = sum + multi;
            add += sum/10;
            sum = sum%10;
        }
        ret[n-2-k] = sum + '0';
        //cout<<n-2-k<<" "<<ret[n-2-k]<<endl;
        sum = 0;//所有进位结束之后对应的累加和变为下一位,累加和设置为0
    }
    //再将最高位设置为进位
    ret[0] = add + '0';//最高位为进位
    //cout<<ret<<endl;
    if(ret[0] == '0'){
        ret.erase(0,1);//删除最高位
    }
    cout<<ret;
    return 0;
}

3.160二维平面上的折线段

思路

计算当前值和需要到达的结点的距离分两种情况

1.距离大于s,此时更新位置并将此时的位置写入

2.距离小于s,此时更新位置和长度,同时指向的结点更新。

具体实现

len:代表的是还需要移动的距离。

diff:代表的是当前位置与结点的距离。

注意事项:需要使用#include<iomanip>来控制输出的精度。

代码

#include<iostream>
#include<vector>
#include<cmath>
#include<iomanip>
using namespace std;
int main(){
    int N;
    cin>>N;
    vector<vector<double>> mp(N,vector<double>(2,0));
    for(int i = 0;i<N;i++){
        cin>>mp[i][0]>>mp[i][1];
    }
    double s;
    cin>>s;
    double len = s;//代表剩余的长度
    vector<vector<double>> ret;
    ret.push_back(mp[0]);
    int i = 1;
    vector<double> cur = mp[0];
    double sz = 0;
    while(i<N){//代表在这个范围之内
        double diff = sqrt((mp[i][0]-cur[0])*(mp[i][0]-cur[0]) + (mp[i][1]-cur[1])*(mp[i][1]-cur[1]));
        //cout<<diff<<" "<<len<<endl;
        if(diff >= len){
            sz = len/diff;
            cur[0] = cur[0] + sz * (mp[i][0]-cur[0]);
            cur[1] = cur[1] + sz * (mp[i][1]-cur[1]);
            ret.push_back(cur);
            len = s;//此时长度重新回到了原来的长度
        }else{
            len = len - diff;//还需要操作的距离
            cur = mp[i];
            i++;
        }
    }
    int n= ret.size();
    std::cout << std::fixed << std::setprecision(5);
    for(int i = 0;i<n;i++){
        cout<<ret[i][0]<<", "<<ret[i][1]<<endl;
    }
    return 0;
}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值