把2移至前方,数字立刻变成两倍

论坛上有人出了这样一道,求一个数,这个数的个位数是2,当把个位上的2移动到最高位的前面时,这个数即为原数的两倍。

一开始我用循环穷举,无果,估计此数可能非常巨大。分析算法后发现可以简化为:

#include <iostream>
using namespace std;
int main( void )
{
 __int64 a = 1, b = 2;
 int p;
 while ( true )
 {
  if ( ( p = (int)( a - ( a / 10 ) * 10 ) ) == 2 && b % a == 0 )
  {
   cout << a << endl;
   break;
  }
  a = ( b = b * 10 + p ) / 2;
 }
 system( "pause" );
 return 0;
}
算法详解如下:

设a为待求值,另有整数b,使得b的值等于a的个位移移动到最高位所得的值,并且a满足两个条件:
1. a的个位数为2
2. b = 2a

算法
E1. 初始a为1,b为2

E2. 求得a的个位数,并赋值予p

E3. 如果p = 2说明a满足该数的第一个条件,如果b能整除a,则满足该数的第二个条件,那么,求得该数,输出结果,退出程序。

E4. 如果不能满足上面两个条件,那么,令b基于10进制向左移一位,并将个位赋为p。(将个位赋予P是为了满足“b的值等于a的个位移移动到最高位所得的值”)

E5. 令a = b / 2

E6. 跳转至E2继续判断。

 

但是该算法并不通用,数字非常巨大,必须使用__int64才能支持运算,并且导致效率低下。经再次优化,得下面纯C代码算法。

#include <stdio.h>
#include <stdlib.h>
int main( void )
{
 int q = 2, a = 1;
 while ( 1 )
 {
  a = q / 2;
  printf( "%d", a );
  if ( q == 4 ) break;
  q = a + ( q % 2 ) * 10;
 }
 return 0;
}

 

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值