翻硬币解析Word下载.docx
- 文档编号:21763794
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:9
- 大小:19.51KB
翻硬币解析Word下载.docx
《翻硬币解析Word下载.docx》由会员分享,可在线阅读,更多相关《翻硬币解析Word下载.docx(9页珍藏版)》请在冰豆网上搜索。
elsebegin
d:
=2*m+1;
t:
=2;
i:
=1;
flag:
=False;
repeat
if(t=1)then
begin
solve:
=②
flag:
=True;
end
elseif(③)then
begin
solve:
=i*m-1;
flag:
endelset:
=④;
i:
=i+1;
untilflag;
end
end;
begin
read(m);
if((m>0)and(m<1000))then
writeln(⑤);
end.
我们把每一次的翻转称为一次“小翻转”,从顶上开始连续翻n次称为一次“大翻转”。
最后翻到全是正面朝上的状态时,如果用了a次大翻转和b次小翻转,那么总的翻转次数是a*n+b。
我们研究一次大翻转的置换结构。
自底向上(为方便我们实际上用自左向右),用1,2,3,...,n标记n个硬币,用a'
表示硬币a的反面朝上状态。
我们还在这一摞硬币的右端放一面镜子,那么,初始状态是:
('
|'
表示镜子的位置)
[1234...n-1n|n'
(n-1)'
...4'
3'
2'
1'
]
经过一次大翻转后,成为:
[246...5'
|135...6'
4'
这个变换很有规律。
只要令a'
=-a,可以看出,一次大翻转就是把编号为c的硬币变换到c/2(mod2n+1)(?
)的位置。
看其逆变缓将更明显。
(偶数是的,奇数应是n-(c+1)/2(mod2n+1)
显然,如果2^m=1(mod2n+1),那么经过m次大翻转后,所有硬币都归到原位而且面朝上。
此时共用了m*n次小翻转。
同样地,如果2^m=-1(mod2n+1),那么经过m次大翻转后,所有硬币都将归到原位,并且正面朝下。
如果不做最后那个大翻转的最后那个n个硬币翻过来的小翻转,那么就能得到正面全朝下的状态,此时需要m*n-1次小翻转。
剩下的问题是,证明只有上面所述两种情况下才会出现正面全朝上的局面。
需要证明几个事实:
1)进行任意次大翻转后,再进行0<
b<
n-1次小翻转,那么不可能出现全部硬币正面朝上的局面。
(即要出现正面全朝上的情况,必然有b=0或b=n-1.)
2)如果经过m次大翻转后全部硬币正面朝上,那么确实每个硬币都回到了原来的位置。
3)如果经过m次大翻转后全部硬币正面朝下,那么确实每个硬币都回到了原来的位置。
2)与3)比较容易证明,证法也类似。
1)证起来麻烦一些。
证明嘛……就不写了。
翻硬币问题的多种求解
一个关于翻硬币的问题,
一摞硬币共有m枚,每一枚都是正面朝上。
输入:
仅有的一个数字是这摞硬币的枚数m,0<
m<
1000。
某单元格输入:
某单元格等于:
下面是我自己的两种解法
[解法一]
思路:
每一轮的翻转后,能得到每一枚硬币当前的位置的位置,如果硬币重新回到原先的位置(基数个硬币时)或者相反的位置(偶数个硬币时),就的到了求解。
//查找每轮循环后的位置
intGetTurnAfterPos(intn,intturn,intm)
{
intTurnNum;
//每轮翻转次数
intTurnAfterPos;
//每轮循环后的位置
TurnNum=turn-n+1;
if(TurnNum%2==0)//为偶数次循环
TurnAfterPos=n+TurnNum/2;
else
//为奇数次循环
TurnAfterPos=(TurnNum+1)/2;
returnTurnAfterPos;
}
//每一轮翻转之后的位置:
intsolve(intturn,int*CurrentPos,intm)
if(turn==0)
return0;
for(inti=0;
i<
turn;
i++)
intRetNum=GetTurnAfterPos(i+1,turn,m);
CurrentPos[RetNum-1]=CurrentPos[m+i];
for(i=0;
m;
CurrentPos[i+m]=CurrentPos[i];
return0;
intmain()
intm=30;
//硬币总数
int*CurrentPos=newint[m*2];
intn=0;
//翻转次数
boolflag=false;
do
{
n++;
m*2;
i++)
CurrentPos[i]=i%m+1;
intx=n/m;
inty=n%m;
for(i=0;
x;
solve(m,CurrentPos,m);
solve(y,CurrentPos,m);
printf("
%d"
CurrentPos[i]);
//solve(5,CurrentPos,m);
/n"
);
if(CurrentPos[i]!
=i+1)
break;
}
if(i==m-1&
&
n>
1)
flag=true;
}
while(!
flag);
if(m%2==0)
翻转的总次数是:
%d/n"
n-1);
else
n);
delete[]CurrentPos;
[解法二]
不管硬币的次序,只是记住每次的翻转和交换,硬币的初始状态都是TRUE,每个COIN经过多伦的翻转后都变回TRUE,那么就求出了解,这是最简单的思路。
voidsolve(intm)
bool*CurrentSurface=newbool[m];
for(inti=0;
CurrentSurface[i]=true;
intturnTimes=0;
boolbSuccess=false;
do
{
for(intj=0;
j<
(i+1)/2;
j++)
//turnCoin(j,i-j+1);
booltemp=CurrentSurface[j];
CurrentSurface[j]=!
CurrentSurface[i-j];
CurrentSurface[i-j]=!
temp;
}
if((i+1)%2==1)
CurrentSurface[i/2]=!
CurrentSurface[i/2];
turnTimes=turnTimes+1;
bSuccess=true;
for(intn=0;
n<
n++)
if(CurrentSurface[n]==false)
bSuccess=false;
break;
if(bSuccess)
}while(!
bSuccess);
printf("
turnTimes);
delete[]CurrentSurface;
intCoinCount=1;
while(CoinCount>
0)
请输入硬币的总数:
"
scanf("
%d"
&
CoinCount);
solve(CoinCount);
网上还有几种解法,也同时列了出来:
[解法三]
这个是最难理解的一个算法,因为没有注释,呵呵。
intsolve(int
m);
intmain()
{
int
do
&
m);
if(m
>
0
m
<
1000)
%d/n/n"
solve(m));
while(m
1000);
solve(int
m)
I,
t,
d,
s=-
1;
//翻转的次数
int
flag;
//如果只有一枚硬币,翻两次就能达到目标
if(m==1)
s=2;
d=2
*
+
//确定硬币是经过偶数次翻转还是奇数次翻转
t=2;
//表示一个COIN必须翻转偶数次,才能从正面继续翻回到正面。
I=1;
//翻转的轮数,每轮为从1翻转到m
flag=0;
//退出循环标志,翻转完成标志
d
=
%d:
d);
/tt(%d)
%d,
/t
s:
%3d,
%3d/n"
I
m,
-
1);
if(t==1)
//
s=I*m;
flag=1;
elseif(t==2*m)
s=I*m-1;
t=(t
2)
%
d;
I=I+1;
s
t
d
s,
return
s;
}
[解法四]
设
题设的从1到n的翻转为一轮番转,位置
pos,
turnNum
为位置pos所需要的翻转次数
,假设有5个硬币,我们按其位置分别编号
1,2,3,4,5
经过一轮翻转后,变成了5,3,1,2,4;
可以看到原来1位置的硬币现在到了3。
这一点说明一轮翻转过后,pos的排列是有规律的,另外,任意位置上的元素的翻转次数为turnNum
=
num+1-pos;
由以上分析得到了,任意位置pos,经过一轮番转后的位置变为了new_pos
num/2
+
1
turnNum/2
-
turnNum%2*turnNum
所以,可以由上式计算出new_pos。
那么,如果new_pos也为1的话,则所有的硬币都回到了原来的位置,且都朝正面。
#include
"
stdio.h"
int
solve(int
m)
{
I
0;
pos,turnNum,temp,s;
if(m
==
1)
s
2;
else
pos
do
I++;
temp
m+1-pos;
+=
temp;
m/2
pos/2
temp%2*(pos/2)*2;
}while(pos!
=1);
I*m
turnNum%2;
//the
sum
of
times
}
return
main()
scanf("
the
is
:
solve(m));
}while(m
!
=
-1);
[解法五]
思路:
直接模拟
#include<
iostream>
#include<
stdlib.h>
#define
swap(a,b){int
t=!
a;
a=!
b;
b
t;
n;
flag[1000];
bool
isright()
for(int
i=0;
i<
n;
i++)
if(!
flag[i])
false;
true;
turncoin()
total
while
(1)
k
total%n;
i,j;
for(
i=0,j=k;
=j;
i++,
j--)
swap(flag[i],flag[j]);
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 硬币 解析