描述
小KITTY想要快速计算整数P的幂 (1 <= P <=10,000),它们需要你的帮助。因为计算极大数的幂,所以它们同一时间仅能使用2个存储器,每个存储器可记录某个结果值。第一件工作是初始化存储器内的值一个为底数x, 另一个为1。 小KITTY可以相乘或相除2个存储器中的值,并把结果存在其中某个存储器内,但所有存储的结果必须是整数。
例如, 如果他们想计算x^31, 一种计算方法是:
WV1 WV2
开始: x 1
存储器1和存储器1相乘,结果存于存储器2: x x^2
存储器2和存储器2相乘,结果存于存储器2: x x^4
存储器2和存储器2相乘,结果存于存储器2: x x^8
存储器2和存储器2相乘,结果存于存储器2: x x^16
存储器2和存储器2相乘,结果存于存储器2: x x^32
存储器2和存储器1相除,结果存于存储器2: x x^31
因此, x^31可以通过6次计算得出。给出要计算的幂次,要求求出最少需要几次计算。
例如, 如果他们想计算x^31, 一种计算方法是:
WV1 WV2
开始: x 1
存储器1和存储器1相乘,结果存于存储器2: x x^2
存储器2和存储器2相乘,结果存于存储器2: x x^4
存储器2和存储器2相乘,结果存于存储器2: x x^8
存储器2和存储器2相乘,结果存于存储器2: x x^16
存储器2和存储器2相乘,结果存于存储器2: x x^32
存储器2和存储器1相除,结果存于存储器2: x x^31
因此, x^31可以通过6次计算得出。给出要计算的幂次,要求求出最少需要几次计算。
输入输出格式
输入
仅一个整数: P
输出
仅一个整数:最少计算次数。
输入输出样例
输入样例
31
输出样例
6
解题思路
别看什么乘啊除的,就看它们的幂相加相减就行就是有a=1,b=0,经过最小次数加减得到p 。
我先用的分支限界枚举深度,然后就五个剪枝在题解里见啦
题解
1 #include<bits/stdc++.h> 2 using namespace std; 3 int p; 4 int qwe;//随手打的,表示深度,分支限界必备 5 int _pow[100];//存2的次方的 6 void dfs(int a,int b,int dep) 7 { 8 if(a<b)//把大的放前面,方便操作 9 swap(a,b); 10 if(dep==qwe+1)//深度达到 11 { 12 if(a==p||b==p)//判断是否有p 13 { 14 cout<<qwe; 15 exit(0);//这里直接停止就可以避免其他搜索,大大节省时间,居家旅行必备 16 } 17 return; 18 } 19 if(a!=0&&b!=0&&p%(__gcd(a,b))!=0)return;//因为a+-b=(a0+b0)*gcd(a,b)=k*gcd(a,b),k为整数,所以p必须能被gcd(a,b) 整除 20 if(a*_pow[qwe-dep+1]<p)return;//极大化剪枝,如果两个数中的大数每次都*2,直到限定深度都不能达到p的值,也没必要做下去,不优秀 21 if(a>p&&b==0)return;//这个只能加自己或减自己,而本来就大所以不能加, 而减就变成0,所以不优秀 22 if(a>2*p)return;//这个一看就知道加到两倍的p去了,肯定不优秀 23 if(a==b)return;//两个数相等和一个数差不多,所以不优秀 24 /*下面8种自己慢慢枚举 25 原来是有12种的,但是0的话就等于只有一个数可操作,不够优秀 26 而加上负数等于减去正数,减去负数等于加上正数,所以这里 用的abs */ 27 dfs(a+b,b,dep+1); 28 dfs(a+b,a,dep+1); 29 30 dfs(abs(a-b),b,dep+1); 31 dfs(abs(a-b),a,dep+1); 32 33 dfs(a+a,b,dep+1); 34 dfs(a+a,a,dep+1); 35 36 dfs(b+b,b,dep+1); 37 dfs(b+b,a,dep+1); 38 } 39 int main() 40 { 41 _pow[0]=1;//0次方是1 42 for(int i=1;i<=16;i++)//枚举2的次方,方便极大化剪枝 43 { 44 _pow[i]=_pow[i-1]*2; 45 } 46 cin>>p; 47 //分支限界 48 for(qwe=1;;qwe++)//一定从0开始,万一碰到那些p==0或者p==1 就等着~~听取WA声一片~~吧 49 { 50 dfs(1,0,1); 51 } 52 return 0; 53 }