1.约瑟夫环2
明明是一名公安局的谈判专家,专门负责和绑匪谈判。有一次,明明接到一个特殊的任务,他赶到了案发现场,发现有k个绑匪绑架了k个人质,于是明明就开始和绑匪进行谈判。绑匪提出了一个非常特殊的要求,如果明明能够回答出这个问题,那绑匪将释放所有的人质;否则,绑匪就要撕票。 绑匪的问题是这样:绑匪把人质和自己围成一个圈,把人质从1开始编号,一直编到k,然后绑匪自己从k+1开始编号,一直编到2k。现在从编号1开始,每次从其中选出第m个人(隔m-1选出一个人)出列,然后绑匪要求明明选定这个m值,且m值要尽量的小,使得最先出列的k个人都是绑匪。 例如:有3个坏人和3个人质,他们排成一圈,其中编号1到3的为人质,编号4到6的为坏人,如下: 1、2、3、4、5、6; 明明要选定m=5时,能够满足绑匪的要求。因为: 第一轮,从1开始数,编号5出列,剩下的人为: 1、2、3、4、6; 第二轮,从6开始数,编号4出列,剩下的人为: 1、2、3、6; 第三轮,从6开始数,编号6出列,剩下的人为: 1、2、3; 这样所有的绑匪都先出列,明明可以成功地救出所有的人质。 如果明明能够找到这个m值,那么所有的人质都想获救,否则的话,后果不堪设想。明明意识到了问题的严重,这个问题对他来说十分地棘手。于是明明想到了你,你是一名程序设计专家,明明想让你用程序来解这个问题,救出所有的人质。 明明的问题可以归结为:假设有k个人质和k个绑匪围成一圈。人质的编号从1到k,绑匪的编号从k+1到2k。从编号1开始,每次从其中选出第m个人(隔m-1选出一人)出列。希望求出m的最小值,使得最先出列的k个人都是绑匪,即都是编号从k+1到2k的人。
个人总结:
1.该题目为环状计算要出列的位置为(当前位置 + m - 1) % 剩余人数,检查:如果出列的是人质(编号≤k),m不符合条件。
#include <iostream>
#include <vector>
using namespace std;
bool checkM(int k, int m) {
int total = 2 * k;
vector<int> people(total);
for (int i = 0; i < total; i++) {
people[i] = i + 1;
}
int currentPos = 0;
int outCount = 0;
while (outCount < k) {
int outPos = (currentPos + m - 1) % people.size();
int outNum = people[outPos];
if (outNum <= k) {
return false;
}
people.erase(people.begin() + outPos);
currentPos = outPos % people.size();
outCount++;
}
return true;
}
int findMinM(int k) {
int m = 1;
while (true) {
if (checkM(k, m)) {
return m;
}
m++;
}
}
int main() {
int k;
while (cin >> k) {
int minM = findMinM(k);
cout << minM << endl;
}
return 0;
}
2.分数化小数
写一个程序,输入一个形如N/D的分数(N是分子,D是分母),输出它的小数形式。
如果小数有循环节的话,把循环节放在一对圆括号中。
例如, 1/3 = .33333333 写成0.(3)
41/333 = 0.123123123... 写成0.(123)
用xxx.0 表示整数
典型的转化例子: 1/3 = 0.(3)
22/5 = 4.4
1/7 = 0.(142857)
2/2 = 1.0
3/8 = 0.375
45/56 = 0.803(571428)
个人总结:
1.先计算商的整数部分(N//D),余数 = N % D;余数 ×10 → 计算当前小数位(余数 ×10 // D);新余数 = (余数 ×10) % D;用哈希表记录每个余数第一次出现的位置,余数重复说明开始循环。
#include <iostream>
#include <vector>
#include <unordered_map>
#include <string>
using namespace std;
int main() {
long long N, D;
cin >> N >> D;
long long integer_part = N / D;
long long remainder = N % D;
string result;
result += to_string(integer_part) + ".";
vector<char> decimal_digits;
unordered_map<long long, int> remainder_pos;
int cycle_start = -1;
int pos = 0;
while (remainder != 0) {
if (remainder_pos.find(remainder) != remainder_pos.end()) {
cycle_start = remainder_pos[remainder];
break;
}
remainder_pos[remainder] = pos;
remainder *= 10;
char digit = '0' + (remainder / D);
decimal_digits.push_back(digit);
remainder = remainder % D;
pos++;
}
for (int i = 0; i < decimal_digits.size(); i++) {
if (i == cycle_start) {
result += "(";
}
result += decimal_digits[i];
}
if (cycle_start != -1) {
result += ")";
}
else if (decimal_digits.empty()) {
result += "0";
}
int len = result.size();
int idx = 0;
while (idx < len) {
int end = min(idx + 76, len);
cout << result.substr(idx, end - idx) << endl;
idx = end;
}
return 0;
}
3.构造序列
序列是在数学世界中一种非常有趣的数字现象,它通过某一规则来产生数字,使数字变得有趣、变幻无穷。很多数学家对序列这种事物产生了浓厚的兴趣,花了很多时间对其进行研究,明明就是其中的一位。一天,他又在研究一种新的序列产生规则,该序列的规则如下:
1) 第1轮,写出两个1,即11;
2) 第2轮,在它们中间插入2,成为121;
3) 第3轮,在上面数中每两个相邻的和为3的数之间插入3,成为13231;
4) 以此类推下去,第n轮,在第n-1轮的数字的基础上,每两个相邻的和为n的数之间插入n。
明明根据这个规则开始构造序列。开始还觉得容易,但是越到后面,明明发现构造序列的计算量越来越大,计算难度也越来越高,计算速度也越来越慢。于是,明明就求助于你这位程序设计专家,能否帮他写一个程序,构造出序列的前9项,然后当明明需要知道序列中的哪一项的时,你就把那一项的数字告诉明明。
明明的问题可以归结为:根据题目描述中所描述的序列产生规则构造序列的前9项,然后告诉你一个正整数n,要求你输出序列的第n项。
个人总结:
1.用字符串存储序列,方便插入操作,逐轮构造:每一轮遍历前一轮的序列,检查相邻和是否等于当前轮数,若是则插入轮数;提前构造好前 9 轮的序列,输入 n 后直接输出,效率极高。用while循环实现多组输入。
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
vector<string> sequences(10);
sequences[1] = "11";
for (int k = 2; k <= 9; k++) {
string prev = sequences[k-1];
string curr;
for (int i = 0; i < prev.size(); i++) {
curr += prev[i];
if (i < prev.size() - 1) {
int a = prev[i] - '0';
int b = prev[i+1] - '0';
if (a + b == k) {
curr += (char)('0' + k);
}
}
}
sequences[k] = curr;
}
int n;
while (cin >> n) {
cout << sequences[n] << endl;
}
return 0;
}
翻译:
在20世纪50年代至70年代期间,随着计算机的使用范围不断扩大,计算机科学的研究重点也相应地扩展到了包括通过编程语言(即用于为计算机编程的特殊语言)来简化计算机的使用,以及开发操作系统(即为计算机和用户之间提供有用接口的计算机程序)等方面。在此期间,计算机科学家们还尝试新的应用和计算机设计,创建了首批计算机网络,并探索了计算与思维之间的关系。
20世纪70年代,计算机芯片制造商开始大规模生产微处理器一一这种电子电路是计算机中主要的信息处理中心。这项新技术彻底改变了计算机行业,大幅降低了计算机的制造成本,并极大地提高了其处理速度。微处理器使得个人电脑的出现成为可能,从而导致了计算机应用的广泛使用。在20世纪70年代初至80年代期间,计算机科学迅速发展,旨在为个人电脑开发新的应用,并推动计算机行业的技术进步。早期的许多研究成果开始通过个人电脑向公众传播,这些电脑的早期软件大多源自现有的概念和系统。
计算机科学家们不断拓展计算机及信息系统领域的边界,他们致力于设计更为复杂、可靠且强大的计算机;使计算机网络能够高效地交换大量信息;并探索让计算机具备智能行为的方法。随着计算机在现代社会中扮演着越来越重要的角色,计算机科学家们努力解决新问题,并发明更好的解决问题的方法。
