SWUN 1428 - 行星球体

28 篇文章 0 订阅
10 篇文章 0 订阅


行星连珠

时间限制(普通/Java) : 8000 MS/ 16000 MS          运行内存限制 : 65536 KByte
总提交 : 57            测试通过 : 5

描述

通常用肉眼望去,当行星差不多处在一条直线上时,人们就称之为“行星连珠”。

 

 

n星连珠是指太阳系的n颗行星在同一时间位于同一条直线。

 

已知这n颗行星都是以太阳为圆心,做匀速圆周运动,且第i颗行星的公转周期为ti天(即绕圆周飞行一圈的时间)。

 

现在,Snow_storm想知道n星连珠每次出现的最少间隔时间是多少?

输入

    输入的第一行为正整数T(T<=300),表示测试组数。

    对于每组测试数据,有一个正整数n(2<=n<=10000),表示有n颗行星

    接下来的一行,共有n个正整数ti(1<=ti<=10000),其中第i个数表示第i颗行星的公转周期。

输出

    对于每组测试数据,输出最少的间隔时间。

样例输入

3
3
5 6 7
4
2 4 6 8
4
5 6 30 60

样例输出

Case 1: 210
Case 2: 24
Case 3: 60

题目来源

YB


 

题目地址: http://218.194.91.48/acmhome/problemdetail.do?&method=showdetail&id=1428

 

刚看到这题,很容易知道,就是求所有数的最小公倍数,但是乘积很大。

 

于是兴奋的写起JAVA大整数~~~

 

N久没写,有点手生。

 

敲完,提交,RE在第5组。

 

查了N久,怀疑数据中含0,除0了。。。  讨论版提问,果然~~

 

重判时,N范围从1000改到了10000。。。 

 

(数据范围为1000时,我的JAVA代码应该是能AC的~~~  囧~   据出题人说:题目数据出水了,范围写错了~~   各种囧)

 

秉着考方法(思路)不考运气的想法,出题人让我的代码华丽的TLE了~~~(写的方法不对~)

 

仔细想下,改用c++敲(比JAVA敲的顺手。。。)。。。

 

思路很简单,先枚举100以内的所有素数(10000开方后是100,所以10000以内的合数肯定有含有100以内的因素。不含有时,该数为质数)。。。

 

然后记录每个素数在所有数中出现了几次。。。

 

重复出现则除去(即除去共同因子)。。。

 

然后用大数乘法储存结果···  (当然这样还TLE了一次,囧,后来特判了一下,当新乘入的数为1时,则不进行大数乘法)。。。

 

算是擦边AC了吧?  虽然数据确实很残暴。。。

 

后来把JAVA代码也改过了~~~~

 

=========================================================================================================

C++代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

struct BigInt{
	int len,num[40000];
	BigInt(){}
	BigInt(int x){
 		len=1;
		num[0]=x;
	}
	void mul(int x){
		int i;
		for(i=0;i<len;i++)
			num[i]*=x;
		for(i=0;i<len-1;i++)
			if(num[i]>=100000){
				num[i+1]+=num[i]/100000;
				num[i]%=100000;
			}
		if(num[len-1]>=100000){
			num[len]=num[len-1]/100000;
			num[len-1]%=100000;
			len++;
		}
	}
	void print(){
		printf("%d",num[--len]);
		while(len--)
			printf("%05d",num[len]);
		puts("");
	}
};

int prime[11000];
int rec[110],cnt;

int gcd(int x){
	int i,j,k,num,res,m;
	res=1;
	for(i=0;i<cnt&& x>=rec[i];i++){
		num=0;
		while(x%rec[i]==0){
			num++;
			x/=rec[i];
		}
		if(num>0){
			if(num<=prime[rec[i]]) continue;
			else{
				m=num-prime[rec[i]];
				prime[rec[i]]=num;
				while(m--)
					res*=rec[i];
			}
		}
	}
	if(x && prime[x]==0){
		res*=x;
		prime[x]=1;
	}
	return res;
}

int init_(){
	memset(prime,0,sizeof(prime));
	int i,j;
	cnt=0;
	for(i=2;i<=100;i++){
		if(prime[i]) continue;
		for(j=i+i;j<=100;j+=i)
			prime[j]=1;
		rec[cnt++]=i;
	}
}

int init_1(){
	memset(prime,0,sizeof(prime));
}

int a[11000];
int cmp(int x,int y){
	return x>y;
}

int main(){
	int t,tt,n,i,tmp;
	BigInt res;
	scanf("%d",&t);
	init_();
	for(tt=1;tt<=t;tt++){
		init_1();
		scanf("%d",&n);
		for(i=0;i<n;i++)
			scanf("%d",&a[i]);
 		sort(a,a+n,cmp);
		res=BigInt(a[0]);
		gcd(a[0]);
		for(i=1;i<n;i++){
			tmp=gcd(a[i]);
			if(tmp==1) continue;
			res.mul(tmp);
		}
		printf("Case %d: ",tt);
		res.print();
	}
	return 0;
}

 

============================================================================================================

JAVA代码:

import java.util.*;
import java.math.*;

public class Main{
	
	static int[] prime = new int[11000];
	static int[] rec = new int[110];
	static int cnt;
	
	static int gcd(int x){
		int i,j,k,num,res,m;
		res=1;
		for(i=0;i<cnt && x>=rec[i];i++){
			num=0;
			while((x%rec[i])==0){
				num++;
				x/=rec[i];
			}
			if(num>0){
				if(num<=prime[rec[i]]) continue;
				else{
					m=num-prime[rec[i]];
					prime[rec[i]]=num;
					while(m>0){
						m--;
						res*=rec[i];
					}
				}
			}
		}
		if(x>1 && prime[x]==0){
			res*=x;
			prime[x]=1;
		}
		return res;
	}
	static void init_(){
		int i,j;
		for(i=0;i<=100;i++)
			prime[i]=0;
		cnt=0;
		for(i=2;i<=100;i++){
			if(prime[i]==1) continue;
			for(j=i+i;j<=100;j+=i)
				prime[j]=1;
			rec[cnt++]=i;
		}
	}
	public static void main(String args[]){
		Scanner cin = new Scanner(System.in);
		int t,tt,n,j,i,tmp,m;
		BigInteger res,now;
		t = cin.nextInt();
		init_();
		for(tt=1;tt<=t;tt++){
			for(j=0;j<=10000;j++) prime[j]=0;
			n=cin.nextInt();
			tmp=cin.nextInt();
			res=BigInteger.valueOf(tmp);
			gcd(tmp);
			for(i=1;i<n;i++){
				tmp=cin.nextInt();
				m=gcd(tmp);
				if(m==1) continue;
				res=res.multiply(BigInteger.valueOf(m));
			}
			System.out.println("Case "+ tt + ": "+ res);
		}
	}
}


 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值