Stein算法主要用于解决超大数取模给欧几里得算法带来局限的问题。
Stein递归算法步骤:Stein(A,B);
1).调整A、B使A>B
2)若A、B都是偶数,则记录下公因子2,然后return 2*Stein(A>>1,B>>1);
3)若A为奇数B为偶数,则return Stein(A,B>>1);
若B为奇数A为偶数,则return Stein(A>>1,B);
4)若两个都为奇数,则return Stein(abs(A-B),B);
理由:设在某一次过程中A、B的最大公因子为D,可得A=k*D,B=h*D;(A>B -> k>h); 所以A-B=|k-h|*D。A,B都为奇数,有奇偶数乘积奇偶性可得D,k,h都为奇数。所以|k-h|一定是偶数,与h互质,所以A-B与B的最大公因数依旧为D。递归成立!
临界条件:if(B==0)return A;
代码:
#include<cstdio>
#include<algorithm>
using namespace std;
int stein(int a,int b){
if(a<b)swap(a,b);
if(b==0)return a;
if((a&1)==0&&(b&1)==0)return stein(a>>1,b>>1)<<1;
else if(a&1&&(b&1)==0)return stein(a,b>>1);
else if(b&1&&(a&1)==0)return stein(a>>1,b);
else return stein(a-b,b);
}
int main(){
printf("%d",stein(18,12));
return 0;
}
咳咳,有件事必须说一下:严格意义上来说,负数和正数之间是没有公因子这一说的【因子要大于0】,但是如果非要求他们的正因子【负因子】,可以先把两个数取绝对值,stein之后再加个符号即可。