3785. 【NOIP2014模拟8.19】分数

Description

在一门叫做计算机应用数学的神奇的课上,老师教给大家如何处理小数的进制转换:
 
p进制的小数abc.def的十进制值为: a*p^2+b*p+c+d/p+e/p^2 +f/p^3 。
 
例如十进制数 1/3 在十进制下小数表示为0.33333…,在三进制下为0.1,在三十进制下为0.A。(这里A的含义与十六进制中A的含义相同,均表示10)。
下课后,老师要求kAc将N个十进制的分数写成k进制下的小数。然而kAc发现,很多十进制分数根本不可能写成有限的k进制小数!这令他十分不爽,不过他想知道,最小需要几进制才能使得这些十进制分数在该进制下均为有限的小数。

Input

第一行一个整数N
接下来N行,每行两个整数a, b,表示一个十进制小数a/b 。

Output

一个整数,表示最小进制数。这里,请按照十六进制输出,所有字母全部大写。(例如,如果答案为十进制下26,则输出1A)。

Sample Input

3
3 99
1 99
1 11

Sample Output

21

Data Constraint

对于20%的测试数据:n=1
对于50%的测试数据:n<=10,a, b <= 10000,保证最终答案在十进制下不超过10000。
对于70%的测试数据:n<=100,a, b<= 10000。
对于100%的测试数据:n<=1000,1 <= a,b <= 1000000000。

Hint

样例解释:
在33进制下,3/99可以表示为0.1,1/99可以表示为0.0B,1/11可以表示为0.3。
可以证明不存在更小的进制,使得他们均为有限小数。

Solution

首先我们将分数化简成最简分数。

考虑十进制下转成x进制时必须不断乘以x,每次取整数部分,知道为0,那么这个x进制必须包含所有的分数中分母所有的因子。

那么答案就是将每个分母质因数分解后将所有不同的质因子乘起来就是答案了。

Code

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define I int
#define ll long long
#define F(i,a,b) for(register I i=a;i<=b;i++)
#define Fd(i,a,b) for(register I i=a;i>=b;i--)
#define mem(a,b) memset(a,b,sizeof(a))
#define N 100010
#define mo 1000000000
using namespace std;
void rd(ll &x){
	x=0;I w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	x*=w;
}
ll n,x,y,d,a[N],bz[N],p[N],tot,r,ans[N];
ll gcd(ll x,ll y){return (x%y==0)?y:gcd(y,x%y);}
void fen(I x){
	F(i,1,tot) if(x%p[i]==0){bz[i]=1;while(x%p[i]==0) x/=p[i];}
	if(x>1){p[++tot]=x;bz[tot]=1;}
}
I main(){
	freopen("fraction.in","r",stdin);
	freopen("fraction.out","w",stdout);
	rd(n);
	F(i,2,N){
		if(!bz[i]) p[++tot]=i;
		for(I j=1;j<=tot,p[j]*i<=N;++j){
			bz[p[j]*i]=1;
			if(p[j]%i==0) break;
		}
	}
	mem(bz,0);
	F(i,1,n){rd(x),rd(y),d=gcd(x,y),y/=d,fen(y);}
	a[0]=a[1]=1;
	F(i,1,tot) if(bz[i]){
		F(j,1,a[0]) a[j]*=p[i];
		F(j,1,a[0]){a[j+1]+=a[j]/mo,a[j]%=mo;}
		while(a[a[0]+1]) a[0]++;
	}
	tot=0;
	while(a[0]){
		r=0;
		Fd(i,a[0],1){r=r*mo+a[i],bz[i]=r/16,r=r%16;}
		ans[++tot]=r,bz[0]=0;
		F(i,1,a[0]){a[i]=bz[i];if(bz[i]) bz[0]=i;}
		a[0]=bz[0];
	}
	Fd(i,tot,1) if(ans[i]<10) printf("%d",ans[i]);else printf("%c",'A'+ans[i]-10);
	return 0;
}
发布了199 篇原创文章 · 获赞 201 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/zsjzliziyang/article/details/103926546