1133. power
Description
从某个未知数x开始,我们可以反复地乘以x,于是我们可以用30次运算就可以算出x^31:
x^2=x*x,x^3=x^2*x,x^4=x^3*x,…..,x^31=x^30*x
显然,平方操作可以缩短这些操作序列。下面是一个仅用8次运算计算x^31的例子:
x^2=x*x,x^3=x^2*x,x^6=x^3*x^3,x^7=x^6*x,x^14=x^7*x^7,x^15=x^14*x,x^30=x^15^x15,x^31=x^30*x
可以证明,7次运算是计算x^31的最少次数了,不过这仅仅是用乘法的时候。
如果可以使用除法的话,我们可以找到一个更短的操作序列。我们只需6次操作即可计算出x^31:
x^2=x*x,x^4=x^2*x^2,x^8=x^4*x^4,x^16=x^8*x^8,x^32=x^16*x^16,x^31=x^32/x
现在你的任务是,仅用乘法和除法,最少需要多少步才能算出x^n。
Input
输入包含多组数据,每组数据一个整数n (1<=n<=1000)
输入以0结束。
Output
求出x^n的最少操作数。
Sample Input
1
31
70
0
Sample Output
0
6
8
Solution
题目大意
给定一个
n
,需要求经过最少多少次乘除运算可以计算出
题解
显然,这题与
x
<script type="math/tex" id="MathJax-Element-3">x</script>无关,所以可以将问题转化为与指数有关的加减运算(初中数学知识).所以很容易就想到了搜索,这题要用到迭代加深,具体就是每次枚举一个最大深度,然后DFS.这是一种BFS和DFS的完美结合,既有BFS的时间上的优势,又有DFS空间上的优势.但是,很不幸地,这样做貌似还会超时,然后加一个神奇的优化应该就能过了(然而我并不会证明_(:з」∠)_,或许正解是打表?).
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std ;
#define N 2000 + 10
bool bz ;
int f[N] , jl[N] ;
int n , mn , cnt = 1 ;
void DFS( int x , int d ) {
if ( d >= mn ) return ;
if ( !f[x] && x <= 1000 ) cnt ++ ;
else if ( f[x] < d ) { bz = 1 ; return ; }
f[x] = d ;
for (int i = 1 ; i <= jl[0] ; i ++ ) {
jl[++jl[0]] = x + jl[i] ;
DFS( x + jl[i] , d + 1 ) ;
jl[jl[0]] = x - jl[i] ;
if ( x - jl[i] > 0 ) DFS( x - jl[i] , d + 1 ) ;
jl[0] -- ;
}
}
int main() {
freopen( "power.in" , "r" , stdin ) ;
freopen( "power.out" , "w" , stdout ) ;
for ( mn = 1 ; mn <= 20 ; mn ++ ) {
bz = 0 ;
jl[1] = jl[0] = 1 ;
DFS( 1 , 0 ) ;
if ( cnt == 1000 ) break ;
}
f[1] = 0 ;
scanf( "%d" , &n ) ;
while ( n ) {
printf( "%d\n" , f[n] ) ;
scanf( "%d" , &n ) ;
}
return 0 ;
}