翻硬币问题的多种求解
[问题描述]
一摞硬币共有m枚,每一枚都是正面朝上。取下最上面的一枚硬币,将它翻面后放回原处。然后取下最上面的2枚硬币,将他们一起翻面后再放回原处。再取3枚,取4枚……直至m枚。然后再从这摞硬币最上面的一枚开始,重复刚才的做法。这样一直做下去,直到这摞硬币中的每一枚又都是正面朝上为止。例如,m为1时,翻两次即可。m为2时,翻3次即可;m为3时,翻9次即可;m为4时,翻11次即可;m为5时,翻24次即可;…;m为30时,翻899次即可;…
输 入:
仅有的一个数字是这摞硬币的枚数m,0<m<1000。
输 出:
为了使这摞硬币中的每一枚又都是正面朝上所必需翻的次数。
某单元格输入:
30
某单元格等于:
899
int GetTurnAfterPos(int n, int turn, int m)
{
int TurnNum ;//每轮翻转次数
int TurnAfterPos; //每轮循环后的位置
TurnNum = turn - n + 1;
if(TurnNum % 2 == 0) //为偶数次循环
TurnAfterPos = n + TurnNum / 2;
else //为奇数次循环
TurnAfterPos = (TurnNum + 1) / 2;
return TurnAfterPos;
}
int solve(int turn, int * CurrentPos, int m)
{
if(turn == 0)
return 0;
{
int RetNum = GetTurnAfterPos(i+1, turn, m);
CurrentPos[RetNum-1] = CurrentPos[m+i];
}
for(i = 0; i < m; i ++)
{
CurrentPos[i+m] = CurrentPos[i];
}
int main()
{
int m = 30;//硬币总数
int * CurrentPos = new int[m*2];
int n = 0;//翻转次数
bool flag = false;
do
{
n++;
for(int i = 0; i < m*2; i++)
CurrentPos[i] = i % m + 1;
int y = n % m;
solve(m, CurrentPos, m);
solve(y, CurrentPos, m);
{
printf("%d ",CurrentPos[i]);
}
//solve(5, CurrentPos, m);
printf("/n");
{
if(CurrentPos[i] != i+1)
{
break;
}
if(i == m - 1 && n > 1)
flag = true;
}
}
while(!flag);
printf("翻转的总次数是: %d/n", n - 1);
else
printf("翻转的总次数是: %d/n", n);
return 0;
}
{
bool * CurrentSurface = new bool[m];
for(int i = 0; i < m; i++)
CurrentSurface[i] = true;
bool bSuccess = false;
do
{
for(int i = 0; i < m; i++)
{
for(int j = 0; j < (i+1) / 2; j ++)
{
//turnCoin(j, i - j + 1);
bool temp = CurrentSurface[j];
CurrentSurface[j] = !CurrentSurface[i - j];
CurrentSurface[i - j] = !temp;
}
if((i+1) % 2 == 1)
CurrentSurface[i/2] = !CurrentSurface[i/2];
for(int n = 0; n < m; n ++)
{
if (CurrentSurface[n] == false)
{
bSuccess = false;
break;
}
}
break;
}
printf("翻转的总次数是: %d/n", turnTimes);
delete [] CurrentSurface;
}
{
int CoinCount = 1;
while(CoinCount > 0)
{
printf("请输入硬币的总数:");
scanf("%d",&CoinCount);
solve(CoinCount);
}
}
{
int m;
do {
scanf("%d", &m);
if(m > 0 && m < 1000)
printf("%d/n/n", solve(m));
} while(m > 0 && m < 1000);
}
int solve(int m)
{
int I,
t,
d,
s = - 1; //翻转的次数
int flag;
//如果只有一枚硬币,翻两次就能达到目标
if(m == 1)
s = 2;
else
{
d = 2 * m + 1; //确定硬币是经过偶数次翻转还是奇数次翻转
t = 2; //表示一个COIN必须翻转偶数次,才能从正面继续翻回到正面。
I = 1; //翻转的轮数,每轮为从1翻转到m
flag = 0; //退出循环标志,翻转完成标志
printf("d = %d:/n", d);
do {
printf("/tt(%d) = %d, /t s: %3d, %3d/n", I, t, I * m, I * m - 1);
if(t == 1) //
{
s = I * m;
flag = 1;
}
else if(t == 2 * m) {
s = I * m - 1;
flag = 1;
}
else
t = (t * 2) % d;
}
} while(!flag);
}
printf("s = %d, I = %d, t = %d, d = %d/n", s, I, t, d);
return s;
}
由以上分析得到了,任意位置pos,经过一轮番转后的位置变为了new_pos = num/2 + 1 + turnNum/2 - turnNum%2*turnNum 所以,可以由上式计算出new_pos。那么,如果new_pos也为1的话,则所有的硬币都回到了原来的位置,且都朝正面。
#include "stdio.h"
int solve(int m)
{
int I = 0;
int pos,turnNum,temp,s;
turnNum = 0;
if(m == 1) s = 2;
else
{
pos = 1;
I = 0;
do
{
I++;
temp = m+1-pos;
turnNum += temp;
pos = m/2 + 1 + pos/2 - temp%2*(pos/2)*2;
}while(pos!=1);
s = I*m - turnNum%2; //the sum of times
}
return s;
}
main()
{
int m;
do
{ scanf("%d",&m);
printf("the sum is : %d/n",solve(m));
}while(m != -1);
}
#include<stdlib.h>
#define swap(a,b){int t=!a; a=!b; b = t;}
int flag[1000];
bool isright()
{
for(int i=0; i<n; i++)
if(!flag[i])
return false;
return true;
}
int turncoin()
{
int total = 1;
while(1)
{
int k = total%n;
int i,j;
for( i=0,j=k; i<=j; i++, j--)
swap(flag[i],flag[j]);
total++;
if(isright())
return total;
}
return total;
}
void init()
{
for(int i=0; i<n; i++)
flag[i] = 1;
flag[0] = 0;
}
int main()
{
while(std::cin >> n && n>0)
{
init();
std::cout << turncoin() << std::endl;
}
return 0;
}
翻硬币问题的多种求解相关推荐
- 蓝桥杯历届试题----矩阵翻硬币
矩阵翻硬币 问题描述 小明先把硬币摆成了一个 n 行 m 列的矩阵.随后,小明对每一个硬币分别进行一次 Q 操作.对第x行第y列的硬币进行 Q 操作的定义:将所有第 i*x 行,第 j*y 列的硬币进 ...
- 浅谈 翻硬币游戏【Nim博弈】
ACM博客_kuangbin 博弈-翻硬币游戏 hihoCoder 1172 : 博弈游戏·Nim游戏·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 Alice和B ...
- 试题 历届试题 翻硬币(贪心)
试题 历届试题 翻硬币 资源限制 时间限制:1.0s 内存限制:256.0MB Work hard,Play harder. 问题描述 小明正在玩一个"翻硬币"的游戏. 桌上放着排 ...
- 蓝桥杯 - 翻硬币(贪心)
小明正在玩一个"翻硬币"的游戏. 桌上放着排成一排的若干硬币.我们用 * 表示正面,用 o 表示反面(是小写字母,不是零). 比如,可能情形是:**oo***oooo ...
- 【DP】翻硬币(jzoj 3921)
翻硬币 jzoj 3921 题目大意: 给你一个长度为nnn的当前01串和目标01串,现在你要做mmm此操作,每次操作你要使kkk个不同的位取反,现在问你有多少种方法可以使当前01串变为目标01串 输 ...
- 牛客14355 翻硬币
链接:https://ac.nowcoder.com/acm/problem/14355 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536 ...
- 蓝桥杯练习系统历届试题 翻硬币
问题描述 小明正在玩一个"翻硬币"的游戏. 桌上放着排成一排的若干硬币.我们用 * 表示正面,用 o 表示反面(是小写字母,不是零). 比如,可能情形是:**oo***oooo 如 ...
- 蓝桥杯试题:矩阵翻硬币
矩阵翻硬币 这是蓝桥杯的一道练习题,题目如下: 问题描述 小明先把硬币摆成了一个 n 行 m 列的矩阵. 随后,小明对每一个硬币分别进行一次 Q 操作. 对第x行第y列的硬币进行 Q 操作的定义:将所 ...
- HDU-3537 Mock Turtles型翻硬币游戏
题意:<=10^8不定个硬币,给你n<=100个正面朝上的硬币以及他们所在的位置,可任选1/2/3个硬币反转(不必连续),但要求翻的这1/2/3个硬币中的最右侧的一个是正面朝上的,问先手者 ...
最新文章
- Oracle数据库物理存储结构管理
- 关于Hinton团队无监督新作SimCLR的所思所想
- python3 模块编写_python3 _pickle模块详解
- (仿头条APP项目)1.app载入界面相关功能实现
- OpenCV学习笔记(五):Mat结构
- JSON-lib 使用
- Jerry Wang重装系统的一些备份
- python菜鸟教程split_Python split()方法
- java集合转换_java各种集合的转换
- oracle数据库相关知识,Oracle数据库相关知识点复习
- 便携本市场一片混乱 东芝也加入战斗
- 小程序坑集【日常总结,持续更新(11.08更新)】
- 两道关于回溯法,分支限界法的算法题
- ie java 注册表,win7在桌面显示IE图标的注册表
- 解析《啊哈C》--最终章:用C语言制作走迷宫和推箱子的小游戏
- python_大智慧SAR指标编写
- android webview静态方法,在android webview中加载静态页面
- Heli Track
- sessionbean+entitybean 在 jbx+wl7中调试笔记。
- CAD学习笔记中级课【导入导出】