克拉兹问题 算法

来源:互联网 发布:99宿舍四级查分软件 编辑:程序博客网 时间:2024/04/27 19:14

/*
克拉兹问题是一个简单有趣而又没有解决的数学问题。这个问题是由L. Collatz在1937年提出的。
  问题如下:
  (1)输入一个正整数n;
  (2)如果n=1则结束;
  (3)如果n是奇数,则n变为3n+1,否则n变为n/2;
  (4)转入第(2)步。
举一个例子:n=13的时候,经历10步可以达到1。
13 -> 40 -> 20 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
还是克拉兹问题。
不过现在是问1000000以内,哪个数变为1需要转化的步骤多。
*/

   这个算法 数太大,真是耗内存。

   当初以为用一个数组可以搞掂的,做一次克拉兹变换,就扫描一次数组,无限耗时间.......

   考虑用vector,手戳,不太会用(因为涉及到在克拉兹变换为1时,就移出这个vector,可变长的vector迭代子有点复杂)

  后来不知怎么的,想到用一个参照数组来保存当前情况,还有一个保存下标的数组,用来保存最初的数字,一切都明朗了



// kelaciwenti.cpp : 定义控制台应用程序的入口点。
//


#include "stdafx.h"
#include <iostream>
using namespace std;




int _tmain(int argc, _TCHAR* argv[])
{



long long const MaxNum=1000000;
long long *pNum=new long long[MaxNum];
int *pSub=new int[MaxNum];
long long cnt;

long long *pCanZhaoNum=new long long [MaxNum];//参照数组
int *pCanZhaoSub=new int[MaxNum];//参照数组下标
long long i,cntCanZhao=0;//cntCanZhao 参照数组长度


pNum[0]=1;
for(i=1; i<MaxNum; i++)
{
pNum[i]=i;
pSub[i]=i;
}


cnt=MaxNum;
while(true)
{
for(i=0; i<cnt; i++)//克拉兹变换
{
if(1 == pNum[i])
continue;
else
{
if( (pNum[i]%2)  ==   0)//偶数
pNum[i]/=2;
else//奇数
pNum[i]=pNum[i]*3+1;
}
}


cntCanZhao=0;
for(i=0; i<cnt; i++)//去掉值为1的数
{
if( (1 == pNum[i]) )
{


}
else
{
pCanZhaoNum[cntCanZhao]=pNum[i];
pCanZhaoSub[cntCanZhao]=pSub[i];
cntCanZhao++;
}
}


if(1 == cntCanZhao)
{
cout<<pCanZhaoSub[cntCanZhao-1];
break;
}


for(i=0; i<cntCanZhao; i++)//从参照数组转移到pNum
{
pNum[i]=pCanZhaoNum[i];
pSub[i]=pCanZhaoSub[i];
}
cnt=cntCanZhao;

}

delete []pNum;
delete []pCanZhaoNum;


getchar();
return 0;
}