不信CSDN真的无人可以理解这种算法的思路!请高人出山!!

lovemysnoopy 2004-11-24 04:49:24
这个题目来自信息学奥赛普及组初赛最后一题,原题是用pascal语言写的
翻硬币: 一摞硬币共有m枚,每一枚都是正面朝上。取下最上面的一枚硬币,将它翻面后放回原处。然后取下最上面的2枚硬币,将他们一起翻面后放回原处。在取3枚,取4枚……直至m枚。然后在从这摞硬币最上面的一枚开始,重复刚才的做法。这样一直做下去,直到这摞硬币中每一枚又是正面朝上为止。例如,m为1时,翻两次即可。
输 入:仅有的一个数字是这摞硬币的枚数m ,0< m <1000。
输 出:为了使这摞硬币中的每一枚都是朝正面朝上所必须翻的次数。
输入样例:30 输出样例:899
int solve(int m)
{ int I,t,d,s; int flag;
if(m==1) s=2 ;
else
{ d=2*m+1; t=2; I=1; flag=0;
do
{ if(t==1)
{ s= I*m ; flag=1;}
else if( t=2*m )
{ s=I*m-1; flag=1; }
else t= (t*2)%d ;
I=I+1;
} while(!flag)
}
return s;
}
void program1( )
{ int m;
scanf(“%d”,&m);
if( m>0 &&m<1000)
printf(“%d\n”,solve(m) );
}
我GOOGLE了很久,包括英文的文章,没有什么收获,看来没有什么特别NB的人真正研究这个,或者研究出来了,只是不愿意说(比如出题的那个家伙,他肯定极其深刻地理解了这个思路);

请教大家I,d,t的含义
说说思路也可以

可以看一下以前讨论的
http://community.csdn.net/Expert/topic/3429/3429252.xml?temp=.9563257
最后的zxlzxlzxl兄的见解很有水准,但兄弟我实在太笨(大家见笑),再请牛人讲解!谢谢了!
...全文
789 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
doface 2004-12-16
  • 打赏
  • 举报
回复
就是一个二进制的数之间的差值 如:1000个硬币就是1后边有999个0,这样的二进制的数是多少,要变成1000个0,就是第一个值 - 0 + 1 即可,最后得出的值就是 2的m次方,就是 2的1000次方,明白了吗?
JustLikeTheWind 2004-12-15
  • 打赏
  • 举报
回复
不好意思,我实在不太明白,为什么2枚硬币需要3次而不是4次?我是不是看漏了什么东西?
过程我想应该是这样的:
1 1
0 1
1 0
0 0
1 1
这样看下来应该是4次啊,为什么上面的2个帖子都说是3次呢?
mxfeng 2004-12-07
  • 打赏
  • 举报
回复
Private Function meneyblow(ByVal meneynum As Integer) As Integer
Dim status(meneynum - 1) As Boolean
Dim ifover As Boolean = False
Dim m As Integer = 1
Dim times As Integer
Do While ifover = False
Dim changed As Boolean
If m = 1 Then
status(m - 1) = Not status(m - 1)
Else
If m Mod 2 = 1 Then
For changednum As Integer = 1 To (m - 1) / 2 Step 1
changed = status(changednum - 1)
status(changednum - 1) = Not status(m - changednum)
status(m - changednum) = Not changed
Next changednum
status((m - 1) / 2) = Not status((m - 1) / 2)
Else
For changednum As Integer = 1 To m / 2 Step 1
changed = status(changednum - 1)
status(changednum - 1) = Not status(m - changednum)
status(m - changednum) = Not changed
Next changednum

End If
End If
times = times + 1
Dim ifovernum As Integer = 0
For i As Integer = 0 To meneynum - 1
If status(i) = False Then
ifovernum += 1
If ifovernum = meneynum Then
ifover = True
Exit Do
End If
ElseIf status(i) = True Then
ifover = False
Exit For
End If
Next
If m = meneynum Then
m = 1
End If
m = m + 1
Loop
MsgBox(times)
End Function

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Call meneyblow(30)
End Sub
wwser 2004-12-03
  • 打赏
  • 举报
回复
我晕哦~~~~~~~
想当年,偶就是在参加湖南省的计算机奥赛时被这道题刷下来嘀~~~~~~
哇呜呜~~~~~~~~~
真他妈地~~~~~
ywyw 2004-11-29
  • 打赏
  • 举报
回复
MARK
fossil2000 2004-11-29
  • 打赏
  • 举报
回复
我的天,头都算大了,还是一团乱麻......正在整理思路中......
关注ing..
土不锅锅 2004-11-29
  • 打赏
  • 举报
回复
我来个Java版的,大家支持java啊!
class Coin implements Cloneable {
private boolean up = true;
//private int index = 0;

protected boolean isUp() {
return up;
}
public void reverse() {
up = !up;
}
//public void setIndex(int index) {
// this.index = index;
//}
//public int getIndex() {
// return index;
//}
public Object clone() {
Object obj = null;
try {
obj = super.clone();
} catch (CloneNotSupportedException e) {}
return obj;
}
}

class Coins {
private int numberOfCoins;
private Coin[] coins;
private int totalCount = 0;

Coins(int n) {
numberOfCoins = n;
coins = new Coin[numberOfCoins + 1];
for (int i = 1; i <= numberOfCoins; i ++) {
coins[i] = new Coin();
//coins[i].setIndex(i);
}
}
public boolean isAllUp() {
for (int i = 1; i <= numberOfCoins; i ++) {
if (!coins[i].isUp())
return false;
}
return true;
}
//某一次你要翻转的硬币数目,例如:你要将从上
//往下的第1到第6枚硬币翻转。
//翻转时包括mark这一枚硬币。
void reverseOneTime(int mark) {
for (int i = 1; i <= mark; i ++)
coins[i].reverse();
for (int i = 1; i <= mark/2; i ++) {
Coin tmp = (Coin)coins[i].clone();
coins[i] = (Coin)coins[mark - i + 1].clone();
coins[mark - i + 1] = tmp;
}
}
public int getTotalCount() {
boolean continued = true;

while (continued) {
int tmp = 0;

for (int i = 1; i <= size(); i ++) {
tmp ++;
reverseOneTime(i);
if (isAllUp()) {
continued = false;
break;
}
}
totalCount += tmp;
}
return totalCount;
}
int size() {
return numberOfCoins;
}
}

public class CoinTest {
public static void main (String[] args) {
for (int i = 1; i <= 30; i ++) {
Coins myCoins = new Coins(i);
System.out.println("number of coins:" + myCoins.size());
System.out.println("total count:" + myCoins.getTotalCount());
}
}
}
qrlvls 2004-11-26
  • 打赏
  • 举报
回复
太复杂了,一看到就头疼
pcboyxhy 2004-11-26
  • 打赏
  • 举报
回复
每枚翻偶数次,
最后枚翻2次,
此时前面的第m-1枚翻了3次,
m-i枚翻了2+i次,
就是这个思路,
迭代求解析式,
很简单的
xdspower 2004-11-26
  • 打赏
  • 举报
回复
一个问题是你的翻一次是指的什么
xiaoxiaofei 2004-11-26
  • 打赏
  • 举报
回复
......这个是算法问题,肯定要考数学思想了.
算法是一定要用到数学滴!!!!!数学思想充满了所有领域~!~!
lovemysnoopy 2004-11-25
  • 打赏
  • 举报
回复
UP
languagec 2004-11-24
  • 打赏
  • 举报
回复
lovemysnoopy 2004-11-24
  • 打赏
  • 举报
回复
to NowCan(((((( ★ )))))) :
谢谢了,我明白一些了,这个题考的哪里是编程啊,完全是数学啊
NowCan 2004-11-24
  • 打赏
  • 举报
回复
这个题目我倒是看过。
http://www.channelwest.com/bbs/showtopic.asp?TOPIC_ID=3193&Forum_ID=9
aheadyes 2004-11-24
  • 打赏
  • 举报
回复
模拟:( 最简单直接的方法。
#include<iostream>
#include<stdlib.h>
#define swap(a,b){int t=!a; a=!b; b = t;}
int n;
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(cin >> n && n>0)
{
init();
cout << turncoin() << endl;
}
return 0;

}

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧