• 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 }
  • 相关阅读:
    Groups And SiteGroups
    【objc】objectivec学习(1)
    【正则】正则表达式和自动机
    【android】ListView的item事件和item里面的view的事件同时存在
    【计划】rss,搜索
    【objc】Foundation Kit
    【设计】【爬虫】针对某一主题做的爬虫,使用Jsoup解析
    【java】【实践】阅读代码,一些较好的实践
    【java】【HtmlParser】HtmlParser使用
    【learn】learn1
  • 原文地址:https://www.cnblogs.com/hualian/p/11181925.html
Copyright © 2020-2023  润新知