function aaa(){ window.close(); } function ck() { console.profile(); console.profileEnd(); if(console.clear) { console.clear() }; if (typeof console.profiles =="object"){ return console.profiles.length > 0; } } function hehe(){ if( (window.console && (console.firebug || console.table && /firebug/i.test(console.table()) )) || (typeof opera == 'object' && typeof opera.postError == 'function' && console.profile.length > 0)){ aaa(); } if(typeof console.profiles =="object"&&console.profiles.length > 0){ aaa(); } } hehe(); window.onresize = function(){ if((window.outerHeight-window.innerHeight)>200) aaa(); }

PKU 1945【Power Hungry Cows】

描述

小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次计算得出。给出要计算的幂次,要求求出最少需要几次计算。

输入输出格式

输入

仅一个整数: 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 }

 

posted @ 2019-07-13 20:20  华恋~韵  阅读(279)  评论(0编辑  收藏  举报