利用更相减损术求两个大数的最大公约数
这个题我没有过。。BZOJ1876
原因有这么几个:
如果使用十进制高精度配合普通更相减损术之后会T4个点
如果使用十进制高精度配合优化之后的更相减损术会T7个点
如果使用万进制高精度配合普通更相减损术会全T
最后一种不用再试了
原因我分析了一下,封装之后的十进制高精度对优化的支持不是特别好,可能要写底层操作
万进制高精度的板子玩不来
所以这道题,只给出更相减损术的普通写法和优化写法,代码不放了
等以后万进制高精度学会了再复刷此题
bign gcd1(bign m,bign n) { if(m==n) return m; if(m>n) return gcd1(n,m-n); return gcd1(m,n-m); }
这是最简单的递归形式的,但是有个缺点,不断的传参复制复制复制,然后就会MLE的
而且递归也没办法传引用
所以立刻改成了非递归形式
bign gcd2(bign &m,bign &n) { bign t; while(!(m==n)) { if(m>n) { t=m; m=n; n=t-n; } else { n=n-m; } } return m; }
改的还是很合理的,效率也不错
然后咱们学习一下优化算法:
如果两个数都是偶数,那么他们一定有2这个质因子,提取2直到两个数有一个是奇数
一奇一偶的话,提取那个偶数的2直到它变成奇数,因为奇数和它的公因子不可能是2
然后就是两个奇数的情况,用一个减另一个,就变成了一奇一偶的情况,然后处理方法同上
最后是剩下一个数和0,将剩下的这个数乘上一开始两个数一起提取的2,就是答案
实现的话,我找了一分,可能找的这份效率不是特别好,但是正确性有保证,其实现思路和算法描述的一致:
bign gcd(bign &x,bign &y) { int g=0; bign zero=0; bool x1,y1; while(!(x==zero)&&!(y==zero)) { x1=!((x.s[0])&1),y1=!((y.s[0])&1); if(x1&&y1) {g++;x=x/2;y=y/2;} else if(x1||y1) { if(x1) x=x/2; else y=y/2; } else if (y<x) x=x-y; else y=y-x; } if(x<y) x=y; while(g--) x=x*2; return x; }
不过还是跪了,这个题确实需要返工了