BZOJ1876: [SDOI2009]SuperGCD
2016-12-13 16:58
357 查看
乍一看觉得是高精度欧几里得……然而算了复杂度后发现不对劲
结果是必修三刚学的更相减损法(当时将这个算法时一直觉得他很辣鸡)
然后百度一下我就不讲了
如果两个数都是偶数,那么他们一定有2这个质因子,提取2直到两个数有一个是奇数
一奇一偶的话,提取那个偶数的2直到它变成奇数,因为奇数和它的公因子不可能是2
然后就是两个奇数的情况,用一个减另一个,就变成了一奇一偶的情况,然后处理方法同上
最后是剩下一个数和0,将剩下的这个数乘上一开始两个数一起提取的2,就是答案
(其实这些都是更相减损术,看不懂可以百度一下)
复杂度的话是O(mlogn),m是n的位数
然后这样做是过不了的会超时
所以需要压位
按理来说压8位应该就过得了了,可是我压了17位我也不知道为什么(我的常数不至于这么大吧)
code:
结果是必修三刚学的更相减损法(当时将这个算法时一直觉得他很辣鸡)
然后百度一下我就不讲了
如果两个数都是偶数,那么他们一定有2这个质因子,提取2直到两个数有一个是奇数
一奇一偶的话,提取那个偶数的2直到它变成奇数,因为奇数和它的公因子不可能是2
然后就是两个奇数的情况,用一个减另一个,就变成了一奇一偶的情况,然后处理方法同上
最后是剩下一个数和0,将剩下的这个数乘上一开始两个数一起提取的2,就是答案
(其实这些都是更相减损术,看不懂可以百度一下)
复杂度的话是O(mlogn),m是n的位数
然后这样做是过不了的会超时
所以需要压位
按理来说压8位应该就过得了了,可是我压了17位我也不知道为什么(我的常数不至于这么大吧)
code:
#include<set> #include<map> #include<deque> #include<queue> #include<stack> #include<cmath> #include<ctime> #include<bitset> #include<string> #include<vector> #include<cstdio> #include<cstdlib> #include<cstring> #include<climits> #include<complex> #include<iostream> #include<algorithm> #define ll long long using namespace std; const int maxn = 11000; const ll N=1e17; struct node { ll a[maxn/14],len; node() { memset(a,0,sizeof a); len=0; } }A,B; void twice(node &x) { for(int i=x.len;i>=1;i--) { x.a[i]<<=1; if(x.a[i]>=N) x.a[i+1]++,x.a[i]-=N; } if(x.a[x.len+1]) x.len++; } void half(node &x) { for(int i=x.len;i>=1;i--) { if(x.a[i]&1ll) x.a[i-1]+=N; x.a[i]>>=1; } if(!x.a[x.len])x.len--; } bool operator <(node x,node y) { if(x.len>y.len) return false; if(x.len<y.len) return true; for(int i=x.len;i>=1;i--) { if(x.a[i]<y.a[i]) return true; if(x.a[i]>y.a[i]) return false; } return true; } node operator -(node x,node y) { int len=x.len; for(int i=1;i<=len;i++) { x.a[i]-=y.a[i]; if(x.a[i]<0) x.a[i]+=N,x.a[i+1]--; } while(!x.a[len]&&len) len--; x.len=len; return x; } int k; void solve() { while(A.a[1]%2==0&&B.a[1]%2==0) { k++; half(A); half(B); } while(A.a[1]%2==0) half(A); while(B.a[1]%2==0) half(B); while(1) { if(A<B) swap(A,B); A=A-B; if(A.len==0) break; while(A.a[1]%2==0) half(A); } } int main() { char str[11000]; int len; scanf("%s",str); len=strlen(str); A.len=(len-1)/17+1; int tk=1; ll dig=1; for(int i=len-1;i>=0;i--) { A.a[tk]+=dig*(str[i]-'0'); dig*=10; if((len-i)%17==0) tk++,dig=1; } scanf("%s",str); len=strlen(str); B.len=(len-1)/17+1; tk=1; dig=1; for(int i=len-1;i>=0;i--) { B.a[tk]+=dig*(str[i]-'0'); dig*=10; if((len-i)%17==0) tk++,dig=1; } if(A.len==1&&A.a[1]==0) { for(int i=B.len;i>=1;i--) printf("%d",B.a[i]); printf("\n"); return 0; } if(B.len==1&&B.a[1]==0) { for(int i=A.len;i>=1;i--) printf("%d",A.a[i]); printf("\n"); return 0; } k=0; solve(); if(A.len==0) A=B; while(k--) twice(A); printf("%lld",A.a[A.len]); for(int i=A.len-1;i>=1;i--) printf("%017lld",A.a[i]); printf("\n"); return 0; }
相关文章推荐
- bzoj1876 [SDOI2009]SuperGCD
- bzoj1876[SDOI2009] SuperGCD
- [BZOJ1876][SDOI2009]superGCD(高精度)
- bzoj1876: [SDOI2009]SuperGCD
- bzoj1876 [SDOI2009]SuperGCD 辗转相减+高精
- BZOJ1876: [SDOI2009]SuperGCD
- 【bzoj1876】[SDOI2009]SuperGCD(高精度)
- bzoj1876 [SDOI2009]SuperGCD
- bzoj1876: [SDOI2009]SuperGCD
- BZOJ1876 [SDOI2009]SuperGCD 【高精 + GCD优化】
- BZOJ1876:[SDOI2009]SuperGCD——C++高精度良心题解
- BZOJ1876 [SDOI2009]SuperGCD 【高精 + GCD优化】
- bzoj 1876 [SDOI2009]SuperGCD
- BZOJ 1876 [SDOI2009] SuperGcd | PY好题
- 数学+高精度——BZOJ1876/Luogu2152 [SDOI2009]SuperGCD
- 【BZOJ】【1876】【SDOI2009】SuperGCD
- [大数GCD Stein算法] BZOJ 1876 [SDOI2009]SuperGCD
- BZOj-[SDOI2009]SuperGCD-Java高精度
- BZOJ 1876: [SDOI2009]SuperGCD
- BZOJ 1876: [SDOI2009]SuperGCD( 更相减损 + 高精度 )