题解:P10494 [USACO02FEB] Power Hungry Cows
思路
读完题,我们不难发现此题中的
为什么是加减呢?我们知道:
而我们计算的是幂,当然是加减啦。
代码分析
本题是一道显然的搜索。但使用 dfs 会由于深度太大而 TLE,使用 bfs 则会 MLE(如果你用了 bitset 就当我没说)。即使卡过此题评测,其效率也不够优秀。那么,我们能否将两者结合呢?这种算法就是著名的 IDDFS。
IDDFS 就是给定一个深度,然后在该深度内进行 dfs,既有 dfs 空间小的优点,又结合了 bfs 速度快的优点,用来解决此题是非常合适的。
但是此题如果只使用 IDDFS 而不优化的话,还是会导致 TLE。因此,我们要对 IDDFS 进行剪枝。
接下来,我们称两幂中较大的一项为
优化 1: 如果
证明:容易证明,
优化 2: 如果
证明:感性理解应该不难接受,如果希望获得严谨的证明,请右转 P4549 题解区。
于是我们可以开开心心的开始 IDDFS 了。
AC Code 1
#include<bits/stdc++.h>
using namespace std;
int ansdep,p;
bool IDA(int x,int y,int dep){
if(x<y) swap(x,y); //保证x不小于y
if(dep==ansdep){ //到达设置深度
if(x==p||y==p) return 1; //返回有解
else return 0;
}
if(x<<(ansdep-dep)<p) return 0; //剪枝1
if(__gcd(x,y)>0&&p%__gcd(x,y)>0) return 0; //剪枝2
if(IDA(x*2,y,dep+1)) return 1;
if(IDA(x*2,x,dep+1)) return 1;
if(IDA(x-y,y,dep+1)) return 1;
if(IDA(x+y,y,dep+1)) return 1;
if(IDA(x-y,x,dep+1)) return 1;
if(IDA(x,y*2,dep+1)) return 1;
if(IDA(x,y+x,dep+1)) return 1;
if(IDA(y,y*2,dep+1)) return 1; //枚举所有情况。由于x不小于y,因此不考虑x-y。
return 0;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>p;
while(!IDA(1,0,0)) //枚举最大深度
++ansdep;
cout<<ansdep;
return 0;
}
再看一眼数据,诶,好像可以打表!
于是:
Code 2(由于代码长度限制无法 AC,仅供娱乐!)
注 1:为什么 IDDFS 每次增加深度都不保存上一层的结论,效率仍然优秀?因为每一次增加深度,新的节点数量会远超上一层的节点。就像此题,每层的
注 2:第一份代码通过了讨论区的 hack。