题目:大整数gcd。
分析:模拟、大数运算。大整数模拟gcd,需要利用大整数乘法、除法和比较,除法使用试商法、即从最高位开始从9-0一次试乘,每位找到乘以除数后第一个小于被除数的数极即为商。
注意:边界数据、1000000000000000000000000000000 / 999999999999999999999999999999
#include <iostream> #include <cstdlib> #include <cstring> #include <stdio.h> using namespace std; char a_in[ 65 ]; char b_in[ 65 ]; int a_ar[ 65 ]; int b_ar[ 65 ]; int a_tp[ 65 ]; int b_tp[ 65 ]; int divr[ 65 ]; int mulr[ 65 ]; int remr[ 65 ]; void output( int *a ) { int end = 30; while ( end >= 1 && !a[end] ) end --; while ( end >= 0 ) printf("%d",a[end --]); } int cmp( int *a, int *b ) { for ( int i = 60 ; i >= 0 ; -- i ) if ( a[i] != b[i] ) return a[i] - b[i]; return 0; } void mul( int *a, int *b, int* c ) { for ( int i = 0 ; i <= 60 ; ++ i ) c[i] = 0; for ( int i = 0 ; i <= 30 ; ++ i ) for ( int j = 0 ; j <= 30 ; ++ j ) c[i+j] += a[i]*b[j]; for ( int i = 0 ; i <= 60 ; ++ i ) { c[i+1] += c[i]/10; c[i] %= 10; } } void div( int *a, int *b, int* c ) { for ( int i = 0 ; i <= 60 ; ++ i ) c[i] = 0; for ( int i = 30 ; i >= 0 ; -- i ) for ( int j = 9 ; j >= 0 ; -- j ) { c[i] = j; mul( b, c, mulr ); if ( cmp( a, mulr ) >= 0 ) break; } } void mod( int *a, int *b, int *r ) { for ( int i = 0 ; i <= 60 ; ++ i ) r[i] = 0; div( a, b, divr ); mul( b, divr, mulr ); for ( int i = 0 ; i <= 60 ; ++ i ) r[i] = a[i] - mulr[i]; for ( int i = 0 ; i <= 60 ; ++ i ) while ( r[i] < 0 ) { r[i+1] -= 1; r[i] += 10; } } void gcd( int *a, int *b ) { int sum = 0; for ( int i = 0 ; i <= 30 ; ++ i ) sum += b[i]; if ( !sum ) return; mod( a, b, remr ); for ( int i = 0 ; i <= 30 ; ++ i ) { a[i] = b[i]; b[i] = remr[i]; } gcd( a, b ); } int main() { int N; char c; while ( cin >> N ) for ( int t = 1 ; t <= N ; ++ t ) { cin >> a_in >> c >> b_in; for ( int i = 0 ; i <= 30 ; ++ i ) a_ar[i] = b_ar[i] = 0; int L_a = strlen(a_in); for ( int i = 0 ; i < L_a ; ++ i ) { a_ar[i] = a_in[L_a-1-i]-'0'; a_tp[i] = a_ar[i]; } int L_b = strlen(b_in); for ( int i = 0 ; i < L_b ; ++ i ) { b_ar[i] = b_in[L_b-1-i]-'0'; b_tp[i] = b_ar[i]; } gcd( a_tp, b_tp ); div( a_ar, a_tp, divr ); output( divr ); cout << " / "; div( b_ar, a_tp, divr ); output( divr ); cout << endl; } return 0; }
/*更快的大整数除法、移位减法*/ void lmove( int *a ) { for ( int i = 60 ; i > 0 ; -- i ) a[i] = a[i-1]; a[0] = 0; } void rmove( int *a ) { for ( int i = 0 ; i < 60 ; ++ i ) a[i] = a[i+1]; } void div( int *a, int *b, int* c ) { for ( int i = 0 ; i <= 60 ; ++ i ) { c[i] = 0; temb[i] = b[i]; tema[i] = a[i]; } int bits = 0; while ( cmp( temb, tema ) < 0 ) { bits ++; lmove( temb ); } while ( bits >= 0 ) { while ( cmp( tema, temb ) >= 0 ) { c[ bits ] ++; for ( int i = 0 ; i < 60 ; ++ i ) tema[i] -= temb[i]; for ( int i = 0 ; i < 60 ; ++ i ) while ( tema[i] < 0 ) { tema[i+1] -= 1; tema[i] += 10; } } rmove( temb ); bits --; } }