分数四则运算(结构)

时间限制: 1 Sec 内存限制: 128 MB

题目描述

分数的分子和分母可用一个结构类型来表示。
编写实现两个分数加(addFS),减(subFS),乘(mulFS),除(divFS)的函数(要求计算结果分数是简化的),以及打印一个分数(printFS),计算两个整数最大公约数的函数(getGCD)。
注意:不能定义全局变量

输入

测试数据的组数 t
第一组第一个分数
第一组第二个分数
第二组第一个分数
第二组第二个分数
……

输出

第一组两个分数的和
第一组两个分数的差
第一组两个分数的积
第一组两个分数的商
第二组两个分数的和
第二组两个分数的差
第二组两个分数的积
第二组两个分数的商
……

样例输入

3
1/2
2/3
3/4
5/8
21/23
8/13

样例输出

7/6
-1/6
1/3
3/4

11/8
1/8
15/32
6/5

457/299
89/299
168/299
273/184

提示

求两数a、b的最大公约数可采用辗转相除法,又称欧几里得算法,其步骤为:

  1. 交换a, b使a > b;
  2. 用a除b得到余数r,若r=0,则b为最大公约数,退出;
  3. 若r不为0,则用b代替a, r代替b,此时a,b都比上一次的小,问题规模缩小了;
  4. 继续第2步。

解决方案

想想化简部分还是可以抽成一个inline函数的,但是懒得改了。

#include <iostream>

class Fraction {
public:
    Fraction() = default;

    Fraction(int numerator, int denominator) : numerator(numerator), denominator(denominator) {}

    Fraction operator+(const Fraction &rhs) {
        int numerator_tmp = this->numerator * rhs.denominator + rhs.numerator * this->denominator;
        int denominator_tmp = this->denominator * rhs.denominator;
        int gcd_tmp = gcd(numerator_tmp, denominator_tmp);
        return {numerator_tmp / gcd_tmp, denominator_tmp / gcd_tmp};
    }

    Fraction operator-(const Fraction &rhs) {
        return (*this + Fraction(-rhs.numerator, rhs.denominator));
    }

    Fraction operator*(const Fraction &rhs) {
        int numerator_tmp = this->numerator * rhs.numerator;
        int denominator_tmp = this->denominator * rhs.denominator;
        int gcd_tmp = gcd(numerator_tmp, denominator_tmp);
        return {numerator_tmp / gcd_tmp, denominator_tmp / gcd_tmp};
    }

    Fraction operator/(const Fraction &rhs) {
        int numerator_tmp = rhs.denominator, denominator_tmp = rhs.numerator;
        return (*this * Fraction(numerator_tmp, denominator_tmp));
    }

    friend std::istream &operator>>(std::istream &is, Fraction &rhs) {
        is >> rhs.numerator;
        is.get();
        is >> rhs.denominator;
        return is;
    }

    friend std::ostream &operator<<(std::ostream &os, const Fraction &rhs) {
        if (rhs.denominator < 0) {
            return os << -rhs.numerator << '/' << -rhs.denominator;
        } else {
            return os << rhs.numerator << '/' << rhs.denominator;
        }
    }

private:
    int numerator, denominator;

    static int gcd(int lhs, int rhs) {
        int tmp;
        while (rhs != 0) {
            tmp = rhs;
            rhs = lhs % rhs;
            lhs = tmp;
        }
        return lhs;
    }
};

int main() {
    size_t T;
    std::cin >> T;
    while (T--) {
        Fraction a{}, b{};
        std::cin >> a >> b;
        std::cout << a + b << std::endl
                  << a - b << std::endl
                  << a * b << std::endl
                  << a / b << std::endl
                  << std::endl;
    }
    return 0;
}

扑克牌排序(结构体)

时间限制: 1 Sec 内存限制: 128 MB

题目描述

自定义结构体表示一张扑克牌,包含类型——黑桃、红桃、梅花、方块、王;大小——2,3,4,5,6,7,8,9,10,J,Q,K,A,小王(用0表示)、大王(用1表示)。输入n,输入n张扑克牌信息,从大到小输出它们的排序结果。
假设扑克牌的排序规则是大王、小王为第一大、第二大,剩余52张扑克牌按照先花色后大小排序。
花色:黑桃>红桃>梅花>方块。
大小: A>K>Q>J>>10>9>…>2。
提示:百度sort函数、strstr函数使用。

输入

测试次数t
每组测试数据两行:
第一行:n,表示输入n张扑克牌
第二行:n张扑克牌信息,格式见样例

输出

对每组测试数据,输出从大到小的排序结果

样例输入

3
5
黑桃4 红桃10 梅花Q 方块K 黑桃A
10
大王 梅花10 红桃K 方块9 黑桃2 梅花A 方块Q 小王 黑桃8 黑桃J
5
红桃K 梅花K 黑桃K 方块K 小王

样例输出

黑桃A 黑桃4 红桃10 梅花Q 方块K
大王 小王 黑桃J 黑桃8 黑桃2 红桃K 梅花A 梅花10 方块Q 方块9
小王 黑桃K 红桃K 梅花K 方块K

提示

解决方案

突然发现我之前发过这题的题解…是我很久以前写的了好像,有兴趣看的话可以直接站内搜索。

如果你试图初始化一个静态的例如某些全局变量,那么可能会得到Clang-Tidy的警告,像这样:Initialization of 'variable_name' with static storage duration may throw an exception that cannot be caught。我不建议无视这个警告。解决方法可以是用一个静态的getter函数来包围这个变量,使得该变量的初始化时机从以前的main()函数执行前延迟到首次调用这个getter函数。下面的get_num_size_map()算是一个小例子,更多信息请访问引用链接。

#include <iostream>
#include <algorithm>
#include <iterator>
#include <map>
#include <sstream>
#include <string>
#include <vector>
#include <cassert>

struct Poker {
    explicit Poker(const std::string &raw) {
        if (raw.find("黑桃") != std::string::npos) {
            this->suit = "黑桃";
        } else if (raw.find("红桃") != std::string::npos) {
            this->suit = "红桃";
        } else if (raw.find("梅花") != std::string::npos) {
            this->suit = "梅花";
        } else if (raw.find("方块") != std::string::npos) {
            this->suit = "方块";
        } else if (raw.find("小王") != std::string::npos) {
            this->suit = "小王";
            this->num = "0";
            return;
        } else {
            this->suit = "大王";
            this->num = "1";
            return;
        }
        if (raw.find("10") == std::string::npos) {
            this->num = raw.back();
        } else {
            this->num = "10";
        }
    }

    size_t size() const {
        size_t size = 0;
        size += get_suit_size_map()[this->suit];
        size += get_num_size_map()[this->num];
        return size;
    }

    bool operator<(const Poker &rhs) {
        return this->size() < rhs.size();
    }

    friend std::ostream &operator<<(std::ostream &os, const Poker &rhs) {
        os << rhs.suit;
        if (!(rhs.num == "0" || rhs.num == "1")) {
            os << rhs.num;
        }
        return os;
    }

    std::string suit, num;
private:
    static std::map<std::string, int> get_suit_size_map() {
        static const std::map<std::string, int> suit_size = {
                {"大王", 5 * 13}, {"小王", 4 * 13},
                {"黑桃", 3 * 13}, {"红桃", 2 * 13},
                {"梅花", 1 * 13}, {"方块", 0 * 13},
        };
        return suit_size;
    }

    static std::map<std::string, int> get_num_size_map() {
        static const std::map<std::string, int> num_size = {
                {"2",  0}, {"3",  1}, {"4",  2}, {"5",  3},
                {"6",  4}, {"7",  5}, {"8",  6}, {"9",  7},
                {"10", 8}, {"J",  9}, {"Q",  10}, {"K",  11},
                {"A",  12}, {"0",  0}, {"1",  0},
        };
        return num_size;
    }
};

int main() {
    size_t T;
    std::cin >> T;
    while (T--) {
        size_t size;
        std::cin >> size;
        if (std::cin.get() == '\r') { std::cin.get(); }
        std::string line;
        std::getline(std::cin, line);
        std::istringstream iss(line);
        std::vector<Poker> pokers{std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>{}};
        assert(!pokers.empty());
        std::sort(pokers.begin(), pokers.end(), [](const Poker &lhs, const Poker &rhs) { return lhs.size() > rhs.size(); });
        std::cout << pokers.front();
        for (size_t i = 1; i < pokers.size(); ++i) {
            std::cout << ' ' << pokers[i];
        }
        std::cout << std::endl;
    }
    return 0;
}

引用:
c++ – How do I iterate over the words of a string? – Stack Overflow
Initialization – cppreference.com
What is this warning in C++: initialization of ‘-‘ with static storage duration may throw an exception that cannot be caught? – Quora
c++ – How to catch exception thrown while initializing a static member – Stack Overflow
c++ – How to deal with static storage duration warnings? – Stack Overflow

访问数组元素(引用)

时间限制: 1 Sec 内存限制: 128 MB

题目描述

输入n,输入n个数,计算n个数的和并输出。
假设主函数定义如下,不可修改。请补齐put函数。

输入

测试次数
每组测试数据一行,正整数n(1~1000),后跟n个整数。

输出

每组测试数据输出一行,即n个整数的和。

样例输入

3
4 10 20 30 40
10 1 2 3 -1 -2 -3 1 2 3 4
5 0 0 0 0 10

样例输出

sum=100
sum=10
sum=10

提示

解决方案

不明白这种混杂着C89和C99还有C++风格的代码有什么理由不让人改

#include <iostream>

const size_t N = 1000;

int &put(int *array, size_t size) {
    return *(array + size);
}

int main() {
    size_t T;
    std::cin >> T;
    while (T--) {
        int array[N]{};
        size_t size;
        std::cin >> size;
        for (size_t i = 0; i < size; ++i) {
            std::cin >> put(array, i);
        }
        int sum = 0;
        for (size_t i = 0; i < size; ++i) {
            sum += array[i];
        }
        std::cout << "sum=" << sum << std::endl;
    }
    return 0;
}

求最大值最小值(引用)

时间限制: 1 Sec 内存限制: 128 MB

题目描述

编写函数void find(int *num,int n,int &minIndex,int &maxIndex),求数组num(元素为num[0],num[1],…,num[n-1])中取最小值、最大值的元素下标minIndex,maxIndex(若有相同最值,取第一个出现的下标。)
输入n,动态分配n个整数空间,输入n个整数,调用该函数求数组的最小值、最大值下标。最后按样例格式输出结果。
改变函数find功能不计分。

输入

测试次数
每组测试数据一行:数据个数n,后跟n个整数

输出

每组测试数据输出两行,分别是最小值、最大值及其下标。具体格式见样例。多组测试数据之间以空行分隔。

样例输入

2
5 10 20 40 -100 0
10 23 12 -32 4 6 230 100 90 -120 15

样例输出

min=-100 minindex=3
max=40 maxindex=2

min=-120 minindex=8
max=230 maxindex=5

提示

解决方案

#include <iostream>

void find(const int *array, size_t size, size_t &min_index, size_t &max_index) {
    for (size_t i = 0; i < size; ++i) {
        if (array[min_index] > array[i]) {
            min_index = i;
        }
        if (array[max_index] < array[i]) {
            max_index = i;
        }
    }
}

int main() {
    size_t T;
    std::cin >> T;
    while (T--) {
        size_t size;
        std::cin >> size;
        int *array = new int[size];
        for (size_t i = 0; i < size; ++i) {
            std::cin >> array[i];
        }
        size_t min_index = 0, max_index = 0;
        find(array, size, min_index, max_index);
        std::cout << "min=" << array[min_index] << " minindex=" << min_index << std::endl
                  << "max=" << array[max_index] << " maxindex=" << max_index << std::endl
                  << std::endl;
    }
    return 0;
}

三数论大小(引用)

时间限制: 1 Sec 内存限制: 128 MB

题目描述

输入三个整数,然后按照从大到小的顺序输出数值。
要求:定义一个函数,无返回值,函数参数是三个整数参数的引用,例如int &a, int &b, int &c。在函数内通过引用方法来对三个参数进行排序。主函数调用这个函数进行排序。
要求:不能直接对三个整数进行排序,必须通过函数而且是引用的方法。

输入

第一行输入t表示有t个测试实例
第二行起,每行输入三个整数
输入t行

输出

每行按照从大到小的顺序输出每个实例,三个整数之间用单个空格隔开

样例输入

3
2 4 6
88 99 77
111 333 222

样例输出

6 4 2
99 88 77
333 222 111

提示

解决方案

#include <iostream>
 
void swap(int &lhs, int &rhs) {
    int tmp = lhs;
    lhs = rhs;
    rhs = tmp;
}
 
void sort(int &a, int &b, int &c) {
    if (c > b) {
        swap(c, b);
    }
    if (c > a) {
        swap(c, a);
    }
    if (b > a) {
        swap(b, a);
    }
}
 
int main() {
    size_t T;
    std::cin >> T;
    while (T--) {
        int a, b, c;
        std::cin >> a >> b >> c;
        sort(a, b, c);
        std::cout << a << ' ' << b << ' ' << c << std::endl;
    }
    return 0;
}

CentOS 安装screenFetch

今天想给虚拟机装个screenFetch,以前在openSUSE和Ubuntu上安装都是直接包管理安装,习惯性地直接yum install screenfetch一下竟然发现没有:

No package screenfetch available.

好吧只好去翻一下文档:Installation · KittyKatt/screenFetch Wiki · GitHub

所以先下载:

wget -O screenfetch-dev https://git.io/vaHfR

然后丢到/usr/bin或类似的目录,如果在PATH就比较方便:

sudo mv ./screenfetch-dev /usr/bin/screenfetch

记得加上可执行权限:

sudo chmod +x /usr/bin/screenfetch

此时应该可以使用了:

screenfetch
screenfetch

好了出现了新的问题,没有lspci,那么:

yum whatprovides lspci
pciutils
sudo yum install pciutils

宽度比较蛋疼,我还是ssh上去截个图吧:

screenfetch

JetBrains Quest (March 13, 2020) Write-Up

废话少说,直接上图:

SGF2ZSB5b3Ugc2VlbiB0aGUgcG9zdCBvbiBvdXIgSW5zdGFncmFtIGFjY291bnQ/

看着像是BASE64编码后的

尝试BASE64解码,可以得到:Have you seen the post on our Instagram account?

所以直达https://jb.gg/kotlin_quest。有一段代码,简单阅读后直接改成这样爆破:

fun main() {
    val s = "Zh#kdyh#ehhq#zrunlqj#552:#rq#wkh#ylghr#iru#wkh#iluvw#hslvrgh#ri#wkh#SksVwrup#HDS1#Li#zh#jdyh#|rx#d#foxh/#lw#zrxog#eh#hdv|#dv#sl1"

    for (n in 1..10) {
        for (c in s) {
            print(c - n)
        }
        print('\n')
    }
}

然后第三行是规律的:We have been working 22/7 on the video for the first episode of the PhpStorm EAP. If we gave you a clue, it would be easy as pi.

那么根据提示就很容易搜到What’s Coming in PhpStorm 2020.1 – EAP Series | Season 2020.1 Episode 122/7pi都似乎在提示3.14,确实3分14秒左右画面出现了抖动,于是开到0.25倍:

右下角设置可以调整播放速率

放慢后注意到了,很明显那个homepage的地址变了一下:

homepage那个键值对的值在3分14秒的时候变成了这个

所以访问https://jb.gg/31415926,JetBrains Quest Quiz,是个答题游戏,建议把他家年度报告打开,还有Google。

第一段还好,第二段就不知道他在bb什么了,不过你会发现首字母都大写了,拿出来好像是一句话:.net day call for speakers blog post image hides the next clue。

那么能找到这篇文章JetBrains .NET Day Online 2020 – Call for Speakers – .NET Tools Blog.NET Tools Blog。图片查看源码能看到文件名写了要去下载版本号为201.6303的社区版IDEA,下一步在每日提示里。然后我就不想干了。

可以在IDEA 2020.1 Quest Build Edition – IntelliJ IDEA – Confluence下载并安装。

每日提示可以在主界面的Help->Tip of the Day中触发,打开主界面的时候默认应该也会打开的。看到大家的图是要求斐波那契数列的第50000000项的前4位和后4位。感觉有点奥数题的样子,应该是能找到规律的,另外我感觉递推来爆破应该问题也不大(Google Codelabs,启动!)。

直接搜的话能看到这篇文章The Mathematical Magic of the Fibonacci Numbers,后4位是15000一个周期,前4位似乎没看到?有空再想想吧,先这样了(先糊弄一下)。

JetBrains Quest (March 11, 2020) Write-Up

第二波解谜,可以在https://twitter.com/jetbrains/status/1237694815283879943找到。

原推文

给出了一段字符串:

.spleh A+lrtC/dmC .thgis fo tuo si ti semitemos ,etihw si txet nehw sa drah kooL .tseretni wohs dluohs uoy ecalp a si ,dessecorp si xat hctuD erehw esac ehT .sedih tseuq fo txen eht erehw si ,deificeps era segaugnal cificeps-niamod tcudorp ehT

仔细看一下就会发现是倒序

比较明显是倒序的,先尝试复原:

fun main() {
    val string = ".spleh A+lrtC/dmC .thgis fo tuo si ti semitemos ,etihw si txet nehw sa drah kooL .tseretni wohs dluohs uoy ecalp a si ,dessecorp si xat hctuD erehw esac ehT .sedih tseuq fo txen eht erehw si ,deificeps era segaugnal cificeps-niamod tcudorp ehT"
    print(string.reversed())
}

会得到:The product domain-specific languages are specified, is where the next of quest hides. The case where Dutch tax is processed, is a place you should show interest. Look hard as when text is white, sometimes it is out of sight. Cmd/Ctrl+A helps.

比较明显:

MPS

来到MPS: The Domain-Specific Language Creator by JetBrains,能发现这里有个:

搜索Dutch tax

打开报告,根据提示,全选来尝试看到白色的文字:

全选即可发现有白色的文字

复制出来可以得到:This is our 20th year as a company, we have shared numbers in our JetBrains Annual report, sharing the section with 18,650 numbers will progress your quest.

所以前往JetBrains 2019 Annual Highlights – Celebrating 20 Years!,找了半天没发现哪里有18650,后面才发现原来是这个加起来刚好是18650:

进去后慢慢翻,有个图片:

有一段火星文?可以慢慢看,也可以看看图片的alt属性:

能勉强看出来是:Did you know JetBrains is always hiring? Check out the kareers(careers) page and see if there is a job for you or a quest challenge to go further at least.

在招聘页面能找到这个Fearless Quester在https://www.jetbrains.com/careers/jobs/fearless-quester-356/,但是忘记截图了,现在已经404了,有点尴尬。

一直觉得自己执行力好差啊…还是要想办法做到今日事今日毕才行…

根据提示后续要到Game Development Tools by JetBrains,用科乐美秘技触发,有一个打砖块游戏,打完砖块就出现了:

字符串合并(指针与函数)

时间限制: 1 Sec 内存限制: 128 MB

题目描述

定义一个函数char *strAdd(char *s1, char *s2),其返回的是s1和s2两个字符串合并后的值。(要求不能改变s1和s2)

输入

测试数据的组数 t
第一组字符串1
第一组字符串2
第二组字符串1
第二组字符串2
…….

输出

第一组字符串1 第一组字符串2 第一组字符串1和字符串2的合并
第二组字符串1 第二组字符串2 第二组字符串1和字符串2的合并
………

样例输入

2
hello
world
string
concatation

样例输出

hello world helloworld
string concatation stringconcatation

提示

解决方案

#include <iostream>
#include <cstring>

char *strcat(char *str1, char *str2) {
    size_t str1_length = strlen(str1), str2_length = strlen(str2);
    auto buffer = new char[str1_length + str2_length + 1];
    auto buffer_ptr = buffer, str1_ptr = str1, str2_ptr = str2;
    while (*str1_ptr) {
        *(buffer_ptr++) = *(str1_ptr++);
    }
    while (*str2_ptr) {
        *(buffer_ptr++) = *(str2_ptr++);
    }
    *buffer_ptr = '\0';
    return buffer;
}

int main() {
    size_t T;
    std::cin >> T;
    while (T--) {
        char str1[1024], str2[1024];
        std::cin >> str1 >> str2;
        std::cout << str1 << ' ' << str2 << ' ' << strcat(str1, str2) << std::endl;
    }
    return 0;
}

函数调用(函数指针)

时间限制: 1 Sec 内存限制: 128 MB

题目描述

定义并实现三个函数:
第一个函数是整数函数,返回类型为整数,参数是一个整数变量,操作是求该变量的平方值
第二个函数是浮点数函数,返回类型为浮点数,参数是一个浮点数变量,操作是求该变量的平方根值。求平方根可以使用函数sqrt(浮点参数),将返回该参数的平方根,在VC中需要头文件cmath。
第三个函数是字符串函数,无返回值,参数是一个字符串指针,操作是把这个字符串内所有小写字母变成大写。
要求:定义三个函数指针分别指向这三个函数,然后根据调用类型使用函数指针来调用这三个函数。不能直接调用这三个函数。
如果类型为I,则通过指针调用整数函数;如果类型为F,则通过指针调用浮点数函数;如果类型为S,则通过指针调用字符串函数

输入

第一行输入一个t表示有t个测试实例
每行先输入一个大写字母,表示调用类型,然后再输入相应的参数
依次输入t行

输出

每行输出调用函数后的结果

样例输入

5
S shenzhen
I 25
F 6.25
I 31
S China

样例输出

SHENZHEN
625
2.5
961
CHINA

提示

解决方案

#include <iostream>
#include <cmath>

int square(int number) {
    return number * number;
}

double square_root(double number) {
    return sqrt(number);
}

void to_upper_case(char *string) {
    while (char ch = *string) {
        if ('a' <= ch && ch <= 'z') {
            *string -= ('a' - 'A');
        }
        string += 1;
    }
}

int main() {
    size_t T;
    std::cin >> T;
    while (T--) {
        char type;
        std::cin >> type;
        switch (type) {
            case 'I': {
                int number;
                std::cin >> number;
                int (*function_ptr)(int) = square;
                std::cout << function_ptr(number) << std::endl;
                break;
            }
            case 'F': {
                double number;
                std::cin >> number;
                double (*function_ptr)(double) = square_root;
                std::cout << function_ptr(number) << std::endl;
                break;
            }
            case 'S': {
                char string[1024];
                std::cin >> string;
                void (*function_ptr)(char *) = to_upper_case;
                function_ptr(string);
                std::cout << string << std::endl;
                break;
            }
            default:
                exit(-1);
        }
    }
    return 0;
}