小米OJ进阶之路——#36选水果
过去属于死神,未来属于自己 ——雪莱
选水果
- 序号:#36
- 难度:非常难
- 时间限制:1500ms
- 内存限制:10M
描述
现在有2k个水果供你挑选,它们按照编号从小到大的顺序依次摆放在一个圆桌上,编号前k的水果由于放的太久已经坏掉了,后k个水果是新鲜的 。现在开始,你可以选择一个正整数m,然后从编号为1的水果开始挑选,每次拿走相隔m的水果。现在要求,在拿到坏水果前,必需把所有的好水果都拿走。问,给定一个k,求满足这个要求的最小的m,现在希望你写一个程序,计算出来这个m。
举例: 现在有6个水果供你选择(k = 3),你选择的数字m=5,那么从1开始,你每拿到的水果编号依次是5,4,6,2,3,1。
输入
一个正整数k,表示有几个新鲜水果与坏水果(0 < k < 14)
输出
一个正整数m,表示挑选水果时的最小相隔
输入样例
3
4
输出样例
5
30
解题思路
在系统上提交N次之后终于成功了,这个题我找到两种解法,一种是较为小白式的,直接循环找每次m对应的坐标,然后判断坐标对应的水果,这种在提交系统后说我超时,于是就果断放弃了这种解法,毕竟既然写程序就要追去高效,那么直接说我的另一种解法 参考约瑟夫环问题
已知:k,n=2*k
求:m
分析:例子 k=3,m=5 1 2 3 4 5 6
以m=5为一循环长度报到m的编号依次为:5,4,6,2,3,1
就是长为n的数组以m为循环长度进行循环,输出报到m的编号
1 2 3 4 5 6 (加粗为开始循环1的编号)
1 2 3 4 6
1 2 3 6
1 2 3
1 3
1
经分析,符合以下规律公式:
data[i]=(data[i-1]+m-1)%(n-i+1)+1; //ans[0]=0
注明:data[i]中的i是指第i次挑到m,其值data[i]是指第i次挑到m的编号
#include <bits/stdc++.h>
using namespace std;
int main()
{
int k;
int m = 0 ;
if (cin >> k && k > 0 && k < 14 )
{
int n = 2 * k;
int m = k + 1;
int data[14];
data[0] = 0;
for (int i = 1; i <= k; i++)
{
data[i] = (data[i - 1] + m - 1) % (n - i + 1);
if (data[i] < k)
i = 0, m++;
}
cout << m << endl;
}
return 0;
}
Programs must be written for people to read, and only incidentally for machines to execute.
代码必须是写给人看的,只是顺便让机器执行。
《计算机程序的构造和解释》
个人C++基础比较薄弱,以上仅限参考,如果大家有更好的解题思路可以加微信:PFEI1214 进行交流学习