1.既约分数
如果一个分数的分子和分母的最大公约数是 1,这个分数称为既约分数。
例如,3/4,1/8,7/1 都是既约分数。
请问,有多少个既约分数,分子和分母都是 1 到 2020 之间的整数(包括 1和 2020)?
题目链接:既约分数
欧几里得算法原理
//返回值则是a和b的最大公约数
int gcd(int a,int b){
return b == 0 ? a:gcd(b,a%b);
}
具体代码如下:
#include <iostream>
using namespace std;
int gcd(int a, int b)
{
return b == 0 ? a:gcd(b, a%b);
}
int main()
{
// 请在此输入您的代码
int count = 0;
for(int i=1; i<2021; i++)
{
for(int j=1;j<2021;j++)
{
if(gcd(i, j) == 1)
{
count++;
}
}
}
cout << count;
return 0;
}
2.分数相加
1/1+1/2+1/4+1/8+⋯
每项是前一项的一半,如果一共有 20 项,求这个和是多少,结果用分数表示出来。
类似:3/2,当然,这只是加了前 2 项而已。分子分母要求互质。
题目链接:分数
找到规律,直接通分出来,甚至不需要约分即可满足分子分母互质的条件
#include <iostream>
using namespace std;
int gcd(int a, int b)
{
return b==0 ? a:gcd(b, a%b);
}
int main()
{
// 请在此输入您的代码
int son=1, mom=1;
for(int i=1;i<20;i++)
{
son = son*2 + 1;
mom = mom * 2;
}
cout << son << '/' << mom;
return 0;
}
3.世纪末星期问题
题目:有邪教称1999年12月31日是世界末日,当然谣言已经不攻自破。还有人称今后的某个世纪末的12月31日,如果是星期一则会....有趣的是,任何一个世纪末的年份的12月31日都不可能是星期一!!!于是"谣言制造商"又修改为星期日.......
1999年12月31日是星期五,请问:未来哪一个离我们最近的一个世纪末年(即XX99年)的12月31日正好是星期天(即星期日)? 回答年份即可.
题目:世纪末星期
就是根据1999年12月31号是周天来进行判断的,统计天数,余数为2就行
#include <iostream>
using namespace std;
int judge_run(int year)
{
if (year%400==0 || (year%4==0 && year%100!= 0))
{
return 1;
}
else
{
return 0;
}
}
int main()
{
int year = 2000;
int day = 0;
// 请在此输入您的代码
for(;year<10000;year++)
{
if(judge_run(year))
{
day += 366;
}
else
{
day += 365;
}
if(year%100==99)
{
day %= 7;
if(day == 2)
{
cout << year;
break;
}
}
}
return 0;
}
4.跑步锻炼
小蓝每天都锻炼身体。
正常情况下,小蓝每天跑 1 千米。如果某天是周一或者月初(1日),为了激励自己,小蓝要跑 2 千米。如果同时是周一或月初,小蓝也是跑 2 千米。
小蓝跑步已经坚持了很长时间,从 2000 年 1 月 1 日周六(含)到 2020 年 10 月 1 日周四(含)。请问这段时间小蓝总共跑步多少千米?
题目链接:跑步锻炼
5.星期一
整个 2020 世纪(1901 年 1 月 1 日至 2000 年 12 月 31 日之间),一共有多少个星期一?
题目链接:星期一
因为2000年12月31日正好是周日,所以直接除以7就可以(可以画个时间轴理解)
#include <iostream>
using namespace std;
int main()
{
// 请在此输入您的代码
int day=0, count=0;
for(int year=2000;year>=1901;year--)
{
if(year%400==0 || (year%4==0 && year%400!=0))
{
day += 366;
}
else
{
day += 365;
}
}
count += day/7;
cout << count;
return 0;
}
6.猜生日
今年的植树节(2012 年 3 月 12 日),小明和他的叔叔还有小伙伴们一起去植树。休息的时候,小明的同学问他叔叔多大年纪,他叔叔说:“我说个题目,看你们谁先猜出来!”
“把我出生的年月日连起来拼成一个 8位数(月、日不足两位前补 0)正好可以被今天的年、月、日整除!”
他想了想,又补充到:“再给个提示,我是 6 月出生的。”
根据这些信息,请你帮小明算一下,他叔叔的出生年月日。
格式是年月日连成的 8 位数。例如,如果是 1948 年 6 月 12 日,就写:19480612。
题目链接:猜生日
这题主要是将年月日转化为整形变量进行计算的问题。
#include <iostream>
using namespace std;
int main()
{
int num=0, judge=0;
int year, day;
for(year=1900;year<=2012;year++)
{
for(day=1;day<=30;day++)
{
num = year*10000 + 600 + day;
if(num%2012==0 && num%6==0 && num%day==0)
{
judge = 1;
break;
}
}
if(judge)
{
cout << year << "060" << day;
break;
}
}
return 0;
}
7.数麦子
你一定听说过这个故事。国王对发明国际象棋的大臣很佩服,问他要什么报酬,大臣说:请在第 1个棋盘格放 1 粒麦子,在第 2 个棋盘格放 2 粒麦子,在第 3 个棋盘格放 4 粒麦子,在第 4 个棋盘格放 8 粒麦子,......后一格的数字是前一格的两倍,直到放完所有棋盘格(国际象棋共有 64 格)。
国王以为他只是想要一袋麦子而已,哈哈大笑。
当时的条件下无法准确计算,但估算结果令人吃惊:即使全世界都铺满麦子也不够用!
请你借助计算机准确地计算,到底需要多少粒麦子。
题目链接:棋盘放麦子
呃,这是大整数的题目,考虑用unsigned long long类型,其实应该记一下各个类型的数据范围,了解一下16禁止表示方法
#include <iostream>
using namespace std;
int main()
{
// 请在此输入您的代码
unsigned long long num=0, a=1;
for(int i=0;i<64;i++)
{
num += a;
a *= 2;
}
cout << num;
return 0;
}
8.分治法(归并排序)
给你一个整数数组
nums
,请你将该数组升序排列。示例 1:
输入:nums = [5,2,3,1] 输出:[1,2,3,5]示例 2:
输入:nums = [5,1,1,2,0,0] 输出:[0,0,1,1,2,5]提示:
1 <= nums.length <= 5 * 104
-5 * 104 <= nums[i] <= 5 * 104
分治法经常的表现形式就是将一个复杂的问题抽象转换为简单的小问题,解决小问题以达到大问题的目的,通常使用迭代来完成,本题目的思路如下:
1.将数组成对分割
2.对每一对数组对应的数字进行比对,新建一个数组,较小者先放入新数组当中,再放较大者,接着继续比对原数组中的下一对数组,直到某一数组到头
3.对还有数字没有放入新数组的数组进行处理,将这些数字放入新的数组,这样就完成了对一对数组的归并,且归并的结果是有序的(升序)
4.将新数组按位置更新到最最开始给的数组当中,继续执行步骤2
代码如下:采用迭代完成
class Solution {
public:
void mysort(vector<int>& nums, int l, int r)
{
if(l >= r)
{
return ;
}
int mid = (l+r)/2;
mysort(nums, l, mid);
mysort(nums, mid+1, r);
int i = l, j= mid+1;
vector<int> tmp;
while(i<=mid && j<=r)
{
if(nums[i]<=nums[j])
{
tmp.push_back(nums[i++]);
}
else
{
tmp.push_back(nums[j++]);
}
}
while(i<=mid)
{
tmp.push_back(nums[i++]);
}
while(j<=r)
{
tmp.push_back(nums[j++]);
}
for(int i=0;i<tmp.size();i++)
{
nums[l+i] = tmp[i];
}
}
vector<int> sortArray(vector<int>& nums) {
mysort(nums, 0, nums.size()-1);
return nums;
}
};
9.汉诺塔问题
一开始我忽视了index变量,以为不需要加上层数,实际上还是要加的,表示移动的层数,可以直接先从主函数开始看,我们的目标就是把A.size()的圈从A移动到B,再看内层,那么我们就需要先把A.size()-1个先移到B,然后把最下面的那个直接放到C,在把移到B的A.size()-1个圈放到C上
个人人为分治的问题的关键在于如何分才能最合理的治理,像归并排序就是分成最小的一对来看,但汉诺塔用最小的(1阶)来看就会比较抽象,从3阶开始看会比较合适,但都从最小开始推,再利用n来验证治理关系,准没有错。
#include <iostream>
#include <vector>
using namespace std;
void myhanoto(vector<int>& A, vector<int>& B, vector<int>& C, int index){
if(index == 0) return;
myhanoto(A, C, B, index-1);
C.push_back(A.back());
A.pop_back();
myhanoto(B, A, C, index-1);
}
int main()
{
vector<int> A, B, C;
A.push_back(2);
A.push_back(1);
A.push_back(0);
myhanoto(A, B, C, A.size());
for(int i=0;i<C.size();i++)
{
cout << C[i] << endl;
}
return 0;
}