题目链接:http://lightoj.com/volume_showproblem.php?problem=1024
题意:给你n(2<=n<=1000)个数, 然后求n个数的最小公倍数,每个数的大小是1---10000;所以答案会很大,可能达到1000个4位数相乘;所以结果很大,将近4000位;
所以一定会涉及到高精度运算;同时我们也不能直接循环求最小公倍数;我们可以把一个数分解成多个质数相乘,然后找到所有数中,出现的质数最多的那个对应的次方,然后再把结果乘起来即可;
例如样例
4
5 6 30 60
5 : 5 //说明最小公倍数的因子中一定有一个5
6 : 2*3 //说明最小公倍数的因子中一定有一个2和一个3;
30 : 2*3*5 //说明最小公倍数的因子中一定有一个2和一个3和一个5;
60 : 2^2*3*5 //说明最小公倍数的因子中一定有2个2和一个3和一个5;
所以我们可以忽略那些个数比较少的, 找到说明结果中一定含有 2个2 1个3 1个5;
需要注意的是,因为每次进行大整数相乘时都是用的N,以至于TLE了无数次,所以可以用多位一起输出的方法进行;
#include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> typedef long long LL; #define N 10001 using namespace std; const double eps = 1e-6; int f[101], p[101], k = 0; void Prime() { for(int i=2; i<101; i++) { if(!f[i])p[k++] = i; for(int j=i; j<101; j+=i) f[j] = 1; } } int ans[1001], cnt[N]; void Mul(int a[], int num) { for(int i=0; i<1000; i++) a[i] = a[i]*num; for(int i=0; i<1000; i++) { a[i+1] += a[i]/10000; a[i] = a[i]%10000; } } void PUTS(int a[]) { int i=1000; while(i>=0 && a[i]==0) i--; printf("%d", a[i--]); while(i>=0) printf("%04d", a[i--]); printf(" "); } int main() { Prime(); int n, T, t = 1; scanf("%d", &T); while(T--) { memset(cnt, 0, sizeof(cnt)); memset(ans, 0, sizeof(ans)); int num; scanf("%d", &n); for(int i=1; i<=n; i++) { scanf("%d", &num); for(int j=0; j<k && p[j]*p[j] <= num; j++) { int s = 0; while(num%p[j] == 0) { s ++; num /= p[j]; } cnt[p[j]] = max(cnt[p[j]], s); } if(num > 1) cnt[num] = max(cnt[num], 1); } ans[0] = 1; for(int i=0; i<N; i++) { if(!cnt[i]) continue; int ret = 1; for(int j=0; j<cnt[i]; j++) ret *= i; Mul(ans, ret); } printf("Case %d: ", t++); PUTS(ans); } return 0; }