快速幂计算题解
7月29日的考试题鸭
首先用广搜比暴力搜索快的多,那么,广搜怎么存状态呢?
当然是可以der(开一手二维的状态保存数组),但是作为一个dalao神级蒟蒻,我们要做完美主义者。
所以应该想到的是跑一手迭代加深 虽然我考试时没想到
一层层搜,时间的话比广搜稍微慢一点,但是胜在无需空间。
看了一下题解有写迭代的,但是没有我这样整(ě)齐(xīn)的,所以想来交一交。
这道题的复杂度大概在O(8^log2(n)) 超时预警
所以我们就需要来一波玄学剪枝,才能使程序拥有飞毛腿般的速度
剪枝就代码里解释:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int n,k; 5 6 int gcd(int x,int y)//判断最大公约数 7 { 8 if(y!=0) 9 return gcd(y,x%y); 10 else 11 return x; 12 } 13 14 bool dfs(int x,int u,int v) 15 { 16 if(x>k) 17 return 0; 18 if(u>v)//我们默认u>v 19 u^=v^=u^=v;//相当于swap(u,v),交换u,v 20 if((v<<(k-x))<n) 21 //即使将所有剩下步数全部用于倍增都无法超过或达到n,则return 0; 22 return 0; 23 if(n%gcd(u,v)) 24 //当容器内的指数的最大公约数不是n的约数时,可以剪枝 25 //因为很明显的是,这种情况下,只能够构造出两个容器内指数的最大公约数的倍数的指数(仔细思考吧233) 26 //这样可以让时间更加接近广搜一点 27 return 0; 28 if(u==v) 29 //此时,只剩下倍增一种操作,劣于u!=v的情况 30 return 0; 31 if(v==n) 32 //达到目标值,停止迭代 33 return 1; 34 //接下来不要眨眼 35 if(dfs(x+1,u+v,v)) 36 return 1; 37 if(dfs(x+1,v+v,v)) 38 return 1; 39 if(dfs(x+1,u+u,v)) 40 return 1; 41 if(dfs(x+1,v-u,v)) 42 return 1; 43 if(dfs(x+1,u,u+v)) 44 return 1; 45 if(dfs(x+1,u,v-u)) 46 return 1; 47 if(dfs(x+1,u,u+u)) 48 return 1; 49 if(dfs(x+1,u,v+v)) 50 return 1; 51 //由于u和v是指数,所以储存器中如果相乘就是指数相加,相除就是指数相减 52 //a^b*a^c=a^(b+c); a^b/a^c=a^(b-c); 53 //所以共八种情况 54 return 0; 55 }
感谢 hyc