面试笔试算法-1

面试笔试算法-欧拉计划
面试笔试算法-二分专题
面试笔试算法-Oj刷题
面试笔试算法-LeetCode刷题
面试笔试算法-STL的使用
面试笔试算法之排列组合与搜索走地图问题

目录结构

    • 欧拉计划
      • 题目1:3或5的倍数
        • 解题技巧:
      • 题目2:偶裴波那锲数
        • 解题思路
        • 代码演示
      • 题目4:最大回文数乘积
        • 解题技巧
      • 题目6:平方的和与和的平方之差
      • 题目8:连续数字最大乘积(滑动窗口法)
        • 思路
        • 题目11:方阵中的最大乘积(方向数组)
        • 思路
      • 题目14:最长考拉兹序列(记忆数组)
        • 思路
        • 记忆化代码:
      • 题目13:大整数加法
        • 思路:
      • 题目25:一千位斐波那锲数(大整数加法)
        • 思路
      • 大整数乘法
        • 思路
      • 题目15:网格路径(递推,通式)
        • 思路
      • Euler-18:数字三角形(数塔问题)
        • 思路
      • Oj590:数塔狂想曲(最长路径和)
      • 题目描述
        • 输入
        • 输出
          • 样例说明
        • 思路:
      • Euler22:姓名得分
        • 思路
        • 代码演示:
        • 新手关于C++ cin 的返回值
      • Euler-32:全数字的乘积
        • 代码演示
      • Euler-33:消除数字的分数(十字相乘)
        • 思路
        • 代码演示:
      • Euler-36:双进制回文数(N进制回文数)
        • 思路:
        • 代码实现
      • Euler-30 各位数字的五次幂(上界估算)
        • 思路

欧拉计划

题目1:3或5的倍数

面试笔试算法-1_第1张图片

解题技巧:

面试笔试算法-1_第2张图片

蓝色框表示3的倍数、绿框是5的倍数、黄框是重复项
利用等差数列分别求出3的倍数的和、5的倍数和相加然后减去重复项15的倍数和
即得结果。时间复杂度为O(1)

#include
using namespace std;

int main(int argc, char *grav[])
{
     
    /* 第一种简单的方法,直接判断是否是3和5的倍数进行输出
    int ans = 0;
    for (int i = 1; i < 1000; i++) {
        if (i % 3 == 0 || i % 5 == 0) {
            ans += i;
        }
    }
    cout << ans << endl;
    */
    // 利用上述技巧编程
    int t3 = (3 + 999) * 333 / 2;
    int t5 = (5 + 995) * 199 / 2;
    int t15 = (15 + 990) * 66 / 2;
    cout << t3 + t5 - t15 << endl;
    return 0;
}

题目2:偶裴波那锲数

面试笔试算法-1_第3张图片

解题思路

面试笔试算法-1_第4张图片

只需要三个变量来回循环利用计可!不断更新a、b、c的值

代码演示

#include
using namespace std;
int main(int argc, char *grav[])
{
     
    int a = 1, b = 1, c = 2, ans = 0;
    while (c <= 4000000) {
     
        if (c % 2 == 0) {
     
            ans += c;
        }
        c = b + c;
        a = b;
        b = c - b;
    }
    cout << ans << endl;
    return 0;
}

题目4:最大回文数乘积

面试笔试算法-1_第5张图片

解题技巧

面试笔试算法-1_第6张图片

首先定义一个临时的变量t用来存储反转后的数字
通过while循环来进行取余求模进行反转
如果t与原始的数据相等则是回文数

#include
using namespace std;

int func(int x) {
     
    int t = 0, row = x;
    while (x) {
     
        t = t * 10 + x % 10;
        x /= 10;
    }
    return t == row;
}

int main(int argc, char *grav[])
{
     
    int ans = 0;
    for (int i = 100; i < 1000; i++) {
     
        for (int j = i; j < 1000; j++) {
     
            int t = i * j;
            if (func(t)) {
     
                ans = max(ans, t);
            }
        }
    }
    cout << ans << endl;
    return 0;
}

题目6:平方的和与和的平方之差

面试笔试算法-1_第7张图片

比较基础,直接计算

#include
using namespace std;
int main(int argc, char *grav[])
{
     
    int sum = 0, psum = 0;
    for (int i = 1; i <= 100; i++) {
     
        sum += i;
        psum += i * i;
    }
    cout << sum * sum - psum << endl;
    return 0;
}

题目8:连续数字最大乘积(滑动窗口法)

面试笔试算法-1_第8张图片

思路

  • 首先将数据复制,保存在本地为字符串
    检查复制后的格式:删掉空格、换行
    读入时用数组存储,读取每位时需转换为数字(- ‘0’)
  • 滑动窗口法
    静态窗口:固定窗口大小
    动态窗口:一般称为双指针
  • 解法:
    使用滑动窗口法——静态窗口
    只需考虑窗口进的数和出的数,可以减少运算次数
    出:除以
    进:乘以
    注意值是否为0
    面试笔试算法-1_第9张图片数据中的关键是对0的处理,首先定义一个0的计数器zero_cnt,进入滑动窗口时:为0时,zero_cnt++,不更新结果,不是0,则乘以原有数的成绩,相反,出滑动窗口时,为0时,zero_cnt–,不是0,原有结果除以要出去的数,当zero_cnt 等于0时,更新答案。
#include
using namespace std;
char num[1005];
long long  ans, zero_cnt, now = 1;
int main(int argc, char *grav[])
{
     
    cin >> num;
    for (int i = 0; i < 1000; i++) {
     
        if (i < 13) {
     
            now *= num[i] - '0';
        } else {
     
            if (num[i] == '0') {
     
                zero_cnt++;
            } else {
     
                now *= num[i] - '0';
            }
            if (num[i - 13] == '0') {
     
                zero_cnt--;
            } else {
     
                now /= num[i - 13] - '0';
            }
        }
        if (!zero_cnt) {
     
            ans = max(ans, now);
        }
    }
    cout << ans << endl;
    return 0;
}
  • 前13位不含0,可以直接计算now
  • 注意窗口内0的情况
    ❗定义一个0的计数器
  • ❌是否可以碰见0就将乘积变为1?
    不行,需要存除除0以外数的乘积
  • ❌是否可以将0直接变为1?可以减少判断次数,只需要对进来的值判断0
    但这样是不可以的,因为有可能不满13位的两个0之间的数很大
    比如11022340111111111111111111
    执行时报错:floating point exception
    除以0了可能会导致该错误
    错误地估计了上界,9^13肯定超过了int类型的上界,所以使用long long
    面试笔试算法-1_第10张图片

题目11:方阵中的最大乘积(方向数组)

面试笔试算法-1_第11张图片

思路

面试笔试算法-1_第12张图片

如上图所示:通过一个简单的矩阵推算出方向数组的八个方向,上(-1, 0)、下(1,0)、左(0,-1)、右(0,1)、右上(-1,1)、右下(1,1)、左下(1,-1)、左上(-1,-1)。

  • 计算某个数各个方向的连续4个数的乘积最大值
    计算问题:为了避免重复,只需要计算连续的4个方向进行计算。
    边界问题:1、判断边界;2、边界补0(至少三圈0)
#include
using namespace std;

int dirx[4] = {
     0, 1, 1, 1};
int diry[4] = {
     1, 1, 0, -1};
int num[30][30], ans;

int main(int argc, char *grav[])
{
     
    for (int i = 5; i < 25; i++) {
     
        for (int j = 5; j < 25; j++) {
     
            cin >> num[i][j];
        }
    }
    for (int i = 5; i < 25; i++) {
     
        for (int j = 5; j < 25; j++) {
     
            // 遍历四个方向
            for (int k = 0; k < 4; k++) {
     
                int t = num[i][j];
                // 四个方向的延伸的四个数
                for (int l = 1; l < 4; l++) {
     
                    int x = i + dirx[k] * l;
                    int y = j + diry[k] * l;
                    t *= num[x][y];
                }
                // meic
                ans = max(ans, t);
            }
        }
    }
    cout << ans << endl;
    return 0;
}

题目14:最长考拉兹序列(记忆数组)

面试笔试算法-1_第13张图片

思路

面试笔试算法-1_第14张图片

将每次计算的递归结果放在一个数组中,下次递归如果数组有值直接返回,避免了重复计算。
递归 + 记忆化 ~= 递推

记忆化代码:

#include
using namespace std;
int num[1000000];
int func(long long n) {
     
    if (n == 1) return 1;
    // 如果数组中有就返回
    if (n < 1000000 && num[n]) return num[n];
    int t;
    if (n % 2 == 0) {
     
        t =  func(n / 2) + 1;
    } else {
     
       t = func(3 * n + 1) + 1;
    }
    // 将每次计算的结果放在数组中,记忆数组
    if (n < 1000000) {
     
        num[n] = t;
    }
    return t;
}

int main(int argc, char *grav[])
{
     
    int ans = 1;
    for (int i = 2; i <= 1000000; i++) {
     
        if (func(ans) < func(i)) {
     
            ans = i;
        }
    }
    cout << ans << endl;
    return 0;
}

题目13:大整数加法

面试笔试算法-1_第15张图片

思路:

面试笔试算法-1_第16张图片

1、将数字1、2反向存在数组中,低位在前,高位在后,数组第一位存数字的长度。
2、定义一个结果数组,用来存储最终结果。
3、进行竖式相加,存储在对应结果数组的位置上。
4、处理进位。从前往后。

#include
#include 
using namespace std;
int num1[105], num2[105], sum[105];
char s1[105], s2[105];
int main(int argc, char *grav[])
{
     
    cin >> s1 >> s2;
    num1[0] = strlen(s1);
    num2[0] = strlen(s2);
    // 数据处理
    for (int i = 0, j = num1[0]; i < num1[0]; i++, j--) {
     
        num1[j] = s1[i] - '0';
    }
    for (int i = 0, j = num2[0]; i < num2[0]; i++, j--) {
     
        num2[j] = s2[i] - '0';
    }
    // 位数多的选为结果数组
    sum[0] = max(num1[0], num2[0]);
    for (int i = 1; i <= sum[0]; i++) {
     
        sum[i] = num1[i] + num2[i];
    }
    for (int i = 1; i <= sum[0]; i++) {
     
        // 处理进位
        if (sum[i] > 9) {
     
            sum[i + 1] += sum[i] / 10;
            sum[i] %= 10;
            // 如果最后一位有进位,则长度要加1
            if (i == sum[0]) {
     
                sum[0]++;
            }
        }
    }
    for (int i = sum[0]; i > 0; i--) {
     
        cout << sum[i];
    }
    cout << endl;
    return 0;
}

题目25:一千位斐波那锲数(大整数加法)

面试笔试算法-1_第17张图片

思路

面试笔试算法-1_第18张图片

两个变量里的大整数循环加即可
int num[2] = {1}; //剩下的自动填充0

#include
using namespace std;
// 采用大整数加法
int func(int *n1, int *n2) {
     
    n2[0] = n1[0];
    for (int i = 1; i <= n2[0]; i++) {
     
        n2[i] += n1[i];
        if (n2[i] > 9) {
     
            n2[i + 1] += n2[i] / 10;
            n2[i] %= 10;
            if (i == n2[0]) {
     
                n2[0]++;
            }
        }
    }
    return n2[0] >= 1000;
}

int main(int argc, char *grav[])
{
     
    int num[2][1100] = {
     {
     1, 1}, {
     1, 1}}; //前两个数初始化位1
    int a = 0, b = 1;
    // 两个变量循环加,死循环
    for (int i = 3; 1; i++) {
     
        // 函数返回值为1,说明超过1000位
        if (func(num[a], num[b]) == 1) {
     
            cout << i << endl;
            break;
        }
        swap(a, b);
    }
    return 0;
}

大整数乘法

思路

面试笔试算法-1_第19张图片

每次存放结果的位置位i + j - 1

#include
#include 

using namespace std;
int main(int argc, char *grav[])
{
     
    char s1[1005], s2[1005];
    // 注意是int类型,char类型会溢出
    int n1[1005] = {
     0}, n2[1005] = {
     0}, ans[1005] = {
     0};
    cin >> s1 >> s2;
    n1[0] = strlen(s1), n2[0] = strlen(s2);
    // i + j - 1
    ans[0] = n1[0] + n2[0] - 1;
    // 处理数据
    for (int i = 1, j = n1[0] - 1; i <= n1[0]; i++, j--) {
     
        n1[i] = s1[j] - '0';
    }
    for (int i = 1, j = n2[0] - 1; i <= n2[0]; i++, j--) {
     
        n2[i] = s2[j] - '0';
    }
    // i + j - 1
    for (int i = 1; i <= n1[0]; i++) {
     
        for (int j = 1; j <= n2[0]; j++) {
     
            ans[i + j - 1] += n1[i] * n2[j];
        }
    }
    // 处理进位
    for (int i = 1; i <= ans[0]; i++) {
     
        if (ans[i] > 9) {
     
            ans[i + 1] += ans[i] / 10;
            ans[i] %= 10;
            if (i == ans[0]) {
     
                ans[0]++;
            }
        }
    }
    // 处理结果
    for (int i = ans[0]; i > 0; i--) {
     
        cout << ans[i];
    }
    cout << endl;
    return 0;
}

题目15:网格路径(递推,通式)

面试笔试算法-1_第20张图片

思路

面试笔试算法-1_第21张图片

1、递推:到达某一个点的路径数只能是从上和左边的路径s

#include
using namespace std;
int main(int argc, char *grav[])
{
     
    // diyizho
    long long dp[25][25] = {
     0};
    for (int i = 1; i <= 21; i++) {
     
        for (int j = 1; j <=21; j++) {
     
            // 左上角(1,1)初始值为1,需要特判赋值
            if (i == 1 && j == 1) {
     
                dp[i][j] = 1;
            } else {
     
                dp[i][j] = dp[i - 1][j] + dp[i][j-1];
            }
        }
    }
    cout << dp[21][21] << endl;
    long long ans = 1;
    for (int i = 40, j = 1; i > 20; i--, j++) {
     
        ans *= i;
        ans /= j;
    }
    cout << ans << endl;

    return 0;
}

Euler-18:数字三角形(数塔问题)

面试笔试算法-1_第22张图片

思路

  • 递推(动态规划)
    自上而下
    面试笔试算法-1_第23张图片
    dp[i][j] = max(dp[i - 1][j - 1], dp[i - 1][j]) + num[i][j]
    遍历最后一行,输出最大值
    自下而上
    面试笔试算法-1_第24张图片
    dp[i][j] = max(dp[i + 1][j + 1], dp[i + 1][j]) + num[i][j]
    最后不需要遍历,最上头就是最大值
  • 补0!
#include
using namespace std;

int n, num[20][20], ans[20][20];

int main(int argc, char *grav[])
{
     
    n = 15;
    for (int i = 1; i <= n; i++) {
     
        for (int j = 1; j <= i; j++) {
     
            cin >> num[i][j];
        }
    }
    /* 自上而下
    int fin = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            ans[i][j] = max(ans[i - 1][j - 1], ans[i - 1][j]) + num[i][j];
            fin = max(fin, ans[i][j]);
        }
    }
    cout << fin << endl;
    */
    // 自下而上
    for (int i = n; i > 0; i--) {
     
        for (int j = 1; j <= i; j++) {
     
            ans[i][j] = max(ans[i + 1][j], ans[i + 1][j + 1]) + num[i][j];
        }
    }
    cout << ans[1][1] << endl;
    return 0;
}

Oj590:数塔狂想曲(最长路径和)

题目描述

​ 相信大家都学过树塔问题,题目很简单求最大化一个三角形数塔从上往下走的路径和。走的规则是:(i,j) 号点只能走向 (i+1,j) 或者 (i+1,j+1)。如下图是一个数塔,映射到该数塔上行走的规则为:从左上角的点开始,向下走或向右下走直到最底层结束。

1

3 8

2 5 0

1 4 3 8

1 4 2 5 0

​ 路径最大和是 1+8+5+4+4=22,1+8+5+3+5=22 或者 1+8+0+8+5=22。

​ 小 S 觉得这个问题 soeasy。于是他提高了点难度,他每次 ban 掉一个点(即规定哪个点不能经过),然后询问你不走该点的最大路径和。当然他上一个询问被 ban 掉的点过一个询问会恢复(即每次他在原图的基础上 ban 掉一个点,而不是永久化的修改)。

输入

第一行包括两个正整数 N,M 分别表示数塔的高和询问次数。

​ 以下 N 行,第 i 行包括用空格隔开的 i−1 个数,描述一个高为 N 的数塔。

​ 而后 M 行,每行包括两个数 X,Y,表示第 X 行第 Y 列的数塔上的点被小 S ban 掉,无法通行。

​ (由于读入数据较大,请使用较为快速的读入方式)

输出

M 行每行包括一个非负整数,表示在原图的基础上 ban 掉一个点后的最大路径和,如果被 ban 掉后不存在任意一条路径,则输出 −1。

  • 样例输入
5 3
1
3 8
2 5 0
1 4 3 8
1 4 2 5 0
2 2
5 4
1 1
  • 样例输出
17
22
-1
样例说明
  • 第一次:
1
3 X
2 5 0
1 4 3 8
1 4 2 5 0

1+3+5+4+4 = 17 或者 1+3+5+3+5=17

  • 第二次:
1
3 8
2 5 0
1 4 3 8
1 4 2 X 0

1+8+5+4+4 = 22

  • 第三次:无法通行,-1!

思路:

面试笔试算法-1_第25张图片

结合数塔问题:
有两种方式可以求得最长路径和,自上而下(红色)、自下而上(绿色)。
此题可以理解为是求去掉某个点,求最大的路径之和。
有自上而下和自下而上两种方式可求得经过某个点所得到的最大路径和,比如18+8-4=22,经过(4,2)的点的最大值为22.
通过此方式可以记录每行最大和次大的数记录下来,如果要去掉的位置是最大的,则次大的为结果,反之亦然。
此解法时间复杂度和空间复杂度都为O(n^2)

#include
#include 
using namespace std;
int n, m, num[1005][1005], utd[1005][1005], dtu[1005][1005], ans[1005][1005], mmax[1005][2];
int main(int argc, char *grav[])
{
     
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
     
        for (int j = 1; j <= i; j++) {
     
            scanf("%d", &num[i][j]);
        }
    }
    // 从上往下求
    for (int i = 1; i <= n; i++) {
     
        for (int j = 1; j <= i; j++) {
     
            utd[i][j] = max(utd[i - 1][j - 1], utd[i - 1][j]) + num[i][j];
        }
    }
    // 从下往上求
    for (int i = n; i > 0; i--) {
     
        for (int j = 1; j <= i; j++) {
     
            dtu[i][j] = max(dtu[i + 1][j], dtu[i + 1][j + 1]) + num[i][j];
        }
    }
    // 求经过每个点得到的最大和
    for (int i = 1; i <= n; i++) {
     
        for (int j = 1; j <= i; j++) {
     
            ans[i][j] = utd[i][j] + dtu[i][j] - num[i][j];
        }
    }
    // 每行最大值的坐标和次大值
    for (int i = 1; i <= n; i++) {
     
        int m2 = 0, m1 = 0, cnt = 0;
        for (int j = 1; j <= i; j++) {
     
            if (ans[i][j] > m1) {
     
                m2 = m1;
                m1 = ans[i][j];
                cnt = j;
            } else if (m2 < ans[i][j]) {
     
                m2 = ans[i][j];
            }
        }
        // 记录下标
        mmax[i][0] = cnt;
        // 记录次大的数
        mmax[i][1] = m2;
    }
    for (int i = 0; i < m; i++) {
     
        int a, b;
        scanf("%d%d", &a, &b);
        if (a == 1 && b == 1) {
     
            printf("-1\n");
        } else if (mmax[a][0] == b) {
     
            printf("%d\n", mmax[a][1]);
        } else {
     
            printf("%d\n", dtu[1][1]);
        }
    }
    return 0;
}

Euler22:姓名得分

面试笔试算法-1_第26张图片

思路

先处理txt文件
字母都是大写
全局替换",“为空格” “,
方便数据读入
:%s /”,"/ /g

  • 读入字符串→sort按字典序排序→计算每个姓名的字母值,乘以其排序后的位置,获得得分→累加得分

代码演示:

#include
#include 
#include 
using namespace std;
int main(int argc, char *grav[])
{
     
    int n = 0;
    string name[6005];
    while (cin >> name[n]) {
     
        n++;
    }
    sort(name, name + n);
    long long ans = 0;
    for (int i = 0; i < n; i++) {
     
        int t = 0;
        for (int j = 0; j < name[i].size(); j++) {
     
            t += name[i][j] - 'A' + 1;
        }
        ans += t * (i + 1);
    }
    cout << ans << endl;

    return 0;
}

新手关于C++ cin 的返回值

cin是C++的标准输入流,其本身是一个对象,并不存在返回值的概念。

不过经常会有类似于 while(cin>>a) 的调用,这里并不是cin的返回值,应该关注">>"输入操作符,其实是它到底返回了什么
“>>”操作重载函数istream& operator>>(istream&, T&);的返回值,其中第二个参数由cin>>后续参数类型决定。
其返回值类型为istream&类型,大多数情况下其返回值为cin本身(非0值),只有当遇到EOF输入时,返回值为0。
所以会有以下这种cin连续读取的方法 cin >> x >> y;
当输入所有数据后,通过输入EOF的方法,可以退出while(cin>>a)这样的循环。 输入EOF的方法,windows下输入ctrl+z,
Linux下输入ctrl+d。 在类似于 ssize_t getline(char **lineptr, size_t *n, FILE *stream); //getline(),在C++手册中显示Return value为input,iuput就是获取数据的流,就是getline的第一个参数
//有类似如下代码,从cin(标准输入流)中获取内容,返回值为获取内容,当遇到EOF时,返回0。

 if(!getline(cin, line)) 
 {
      
     break; 
 }

Euler-32:全数字的乘积

面试笔试算法-1_第27张图片
思路
面试笔试算法-1_第28张图片

  • 全数字概念:xx * xxx = xxxx,存在1~9每个数字一次
  • 没有0!
  • 避免重复计算
    • 第一个数字比第二个数字小
    • 第一个数字:范围1~100,当其为100时,第二个数字至少为100,三数位数和超过9
    • 第二个数字:停止条件为三个数字位数之和大于9
    • 使用log10判断位数:log10下取整+ 1
    • 对于正数转int和下取整效果一样,下取整后得到double还需要转int
  • 如何判断全数字
    • <9不需要判断,只有=9才判断,>9停止
    • 使用num[10]存储9个数字的状态
    • 乘积可从多个乘法等式中得到,但只求和一次
    • 使用标记数组,如果之前存过,就跳过

代码演示

#include
#include 
using namespace std;
//  判断数字的位数
int digit(int x) {
     
     // 先取对数,下取整,强转, 加1
    return (int)floor(log10(x)) + 1;
}

int check(int x, int *num) {
     
    while(x) {
     
        if (num[x % 10] == 1) {
     
            return 0;
        }
        num[x % 10] = 1;
        x /= 10;
    }
    return 1;
}
// 判断是否全数字
int func(int a, int b, int c) {
     
    // 标记数组,第一个数初始化为1
    int num[10] = {
     1};
    if (check(a, num) == 0) return 0;
    if (check(b, num) == 0) return 0;
    if (check(c, num) == 0) return 0;
    return 1;
}

int main(int argc, char *grav[])
{
     
    int ans = 0, mark[10005] = {
     0};
    for (int i = 1; i < 100; i++) {
     
        for (int j = i + 1; 1; j++) {
     
            int a = digit(i), b = digit(j), c = digit( i * j);
            // 位数等于9处理一波
            if (a + b + c == 9) {
     
                if (func(i, j, i * j)) {
     
                    // mark数组用来去重
                    if (mark[i * j] == 0) {
     
                        mark[i * j] = 1;
                        ans += i * j;
                    }
                    cout << i << " * " << j << "=" << i * j << endl; 
                }
            } else if (a + b + c > 9) {
     
                break;
            }
        }
    }
    cout << ans << endl;
    return 0;
}

Euler-33:消除数字的分数(十字相乘)

面试笔试算法-1_第29张图片

思路

面试笔试算法-1_第30张图片

  • 有趣

有四个非平凡的例子,求四个分数的乘积化为最简分数后的分母值 不考虑平凡解,即有0存在,不用考虑太细,可以直接要求每位都不为0
分子分母都是两位数,分母比分子大
分子:11 - 99;
分母:分子 + i
四种抹除方式 :
1、分子1 = 分母1;2、分子1 = 分母2;3、分子2 = 分母1;4、分子2 = 分母2
抹除前后判等:十字相乘

代码演示:

#include
using namespace std;
int check(int a, int b) {
     
    int x1 = a / 10, x2 = a % 10;
    int y1 = b / 10, y2 = b % 10;
    if (!x1 || !x2 || !y1 || !y2) return 0;
    if (x1 == y1 && a * y2 == b * x2) return 1;
    if (x1 == y2 && a * y1 == b * x2) return 1;
    if (x2 == y1 && a * y2 == b * x1) return 1;
    if (x2 == y2 && a * y1 == b * x1) return 1;
    return 0;
}
int gcd(int a, int b) {
     
    if (!b) return a;
    return gcd(b, a % b);
}
int main(int argc, char *grav[])
{
     
    int a = 1, b = 1;
    for (int i = 11; i < 100; i++) {
     
        for (int j = i + 1; j < 100; j++) {
     
            if (check(i, j)) {
     
                a *= i;
                b *= j;
                cout << i << "/" << j << endl;
            }
        }
    }
    int c = gcd(a, b);
    cout << b / c << endl;
    return 0;
}

Euler-36:双进制回文数(N进制回文数)

面试笔试算法-1_第31张图片

思路:

  • 前导0处理 : 如0012332100,不作为回文数
int num;
cin >> num;
// 00123 正常读入为 123

代码实现

#include
using namespace std;
// n代表进制
int check(int x, int n) {
     
    int raw = x, t = 0;
    while (x) {
     
        t = t * n + x % n;
        x /= n;
    }
    return t == raw;
}
int main(int argc, char *grav[])
{
     
    int ans = 0;
    for (int i = 1; i < 1000000; i++) {
     
        if (check(i, 10) && check(i, 2)) {
     
            ans += i;
            cout << i << endl;
        }
    }
    cout << ans << endl;
    return 0;
}

Euler-30 各位数字的五次幂(上界估算)

面试笔试算法-1_第32张图片

思路

面试笔试算法-1_第33张图片
重点五次幂之和的最大范围?

设一个X位数
其最大五次幂之和为 9^5 * X
X位数上界为 10^X
估计两个值的交点,即9^5 * X = 10^X,X大约为 5.xxx
所以X最大为 6

枚举10 ~ 1000000
⭐提前算好1 ~ 9的五次幂,存起来!

#include
using namespace std;

int num[10];
// 先求每个数的五次方
void init() {
     
    for (int i = 1; i < 10; i++) {
     
        int t = i;
        for (int j = 1; j < 5; j++) {
     
            t *= i;
        }
        num[i] = t;
    }
}

int check(int x) {
     
    int raw = x, t = 0;
    while (x) {
     
        t += num[x % 10];
        x /= 10;
    }
    return raw == t;

}

int main(int argc, char *grav[])
{
     
    init();
    int ans = 0;
    for (int i = 10; i < 1000000; i++) {
     
        if (check(i)) {
     
            ans += i;
            cout << i << endl;
        }
    }
    cout << ans << endl;
    return 0;
}

你可能感兴趣的:(C&C++,数据结构--C++实现代码,c++)