3785. 【NOIP2014模拟8.19】分数 (File IO): input:fraction.in output:fraction.out

 

Time Limits: 2000 ms  Memory Limits: 131072 KB  Detailed Limits  

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。
可以证明不存在更小的进制,使得他们均为有限小数。

 

考场:

比赛时本以为能切。

考虑一个fraction a / b 在 k进制下是有限的那么 必定存在 一整数P, 使 bp = k^x次方。

所以p = k ^ x / b, p是整数

那么我们得到一个结论:k分解质因数后包含b的所有质因子。

那么就简单了, 分解, 去重, 乘起来, 转16进制。

可惜我tm没打高精度。

我以为:

假设多个b分解质因子后, 质因子都不相同, 那么乘积每次乘10^9。

一共1000个数, 那么就是10^12。

错了

是(10^9)^1000 = 10^9000

乘积

 

#include<bits/stdc++.h>
#pragma GCC optimize(2,3,"Ofast","inline","-fgcse","-fgcse-lm","-fipa-sra","-ftree-pre","-ftree-vrp","-fpeephole2","-ffast-math","-fsched-spec","unroll-loops","-falign-jumps","-falign-loops","-falign-labels","-fdevirtualize","-fcaller-saves","-fcrossjumping","-fthread-jumps","-funroll-loops","-fwhole-program","-freorder-blocks","-fschedule-insns","inline-functions","-ftree-tail-merge","-fschedule-insns2","-fstrict-aliasing","-fstrict-overflow","-falign-functions","-fcse-skip-blocks","-fcse-follow-jumps","-fsched-interblock","-fpartial-inlining","no-stack-protector","-freorder-functions","-findirect-inlining","-fhoist-adjacent-loads","-frerun-cse-after-loop","inline-small-functions","-finline-small-functions","-ftree-switch-conversion","-foptimize-sibling-calls","-fexpensive-optimizations","-funsafe-loop-optimizations","inline-functions-called-once","-fdelete-null-pointer-checks")
#define open(x) freopen(x".in", "r", stdin);freopen(x".out", "w", stdout)
#define mem(a, b) memset(a, b, sizeof(a))
#define mcy(a, b) memcpy(a, b, sizeof(a))
#define pf printf
#define sf scanf
#define fo(i, a, b) for( ll i = a; i <= b; ++i) 
#define fown(i, a, b) for( ll i = a; i >= b; --i)
#define em(p, x) for(ll p=tail[x];p;p=e[p].fr)
#define ll long long
#define wt(a, c, d, s) fo(i, c, d) pf((s), a[i]); puts("")
#define rd(a, c, d) fo(iii, c, d) in((a)[i])
#define N 5050
#define inf 147483647
#define mod (ll)(1e9 + 7)
#define maxn (1e9+1)
using namespace std;

template<class T> 
T in(T &x) {
	x=0;
	char ch = getchar(); ll f = 0;
	while(ch < '0' || ch > '9') f |= ch == '-', ch = getchar();
	while(ch >= '0' && ch <= '9') x = (x<<1) + (x<<3) + ch - '0', ch = getchar();
	x = f ? -x : x;
	return x;
}

ll n, i, j, ans;
ll a, b, A[30010], len;
set<ll> s;

 ll ss(ll x) {
	ll up = sqrt(x);
	for(register ll j = 2 ; j <= up ; ++j) if(x % j == 0 ) return 0;
	return 1;
}
const ll tp = 100;

struct bignum {
	ll len, a[10000];
	bignum() {mem(a, len = 0);}
	ll val() {
		ll ret = 0;
		fown(i, len, 1) ret = ret * 10 + a[i];
		return ret;
	}
	
	bignum operator * (ll x) {
		bignum a = *this;
		fo(i, 1, a.len) a.a[i] *= x;
		fo(i, 1, a.len) {
			a.a[i + 1] += a.a[i] / 10;
			if(a.a[a.len + 1]) a.len++;
			a.a[i] %= 10;
		}
		return a;
	}
	
	ll operator % (ll x) {
		bignum a = *this;
		ll r = 0;
		fown(i, a.len, 1) {
			r = r * 10 + a.a[i];
			r = r % x;
		}
		return r;
	}
	
	bignum operator / (ll x) {
		bignum a = *this;
		ll r = 0;
		fown(i, a.len, 1) {
			r = r * 10 + a.a[i];
			a.a[i] = r / x;
			r = r % x;
		}
		while(a.a[a.len] == 0 && a.len) --a.len;
		return a;
	}
	void operator = (ll x) {
		while(x) {
			this->a[++this->len] = x % 10;
			x /= 10;
		}
		return ;
	}
	bool operator < (bignum x) {
		ll lena = this->len, lenb = x.len;
		if(lena < lenb) return 1;
		if(lena > lenb) return 0;
		fown(i, lena, 1) if(this->a[i] < x.a[i]) return 1; else if(this->a[i] > x.a[i])return 0;
		return 0;
	}
}sum;

ll check(bignum x) {
	bignum tmp;
	tmp = 16;
	if(x < tmp) return 0;
	return 1;
}

ll gcd(ll m, ll n) {
	if(n == 0 ) return m;
	return gcd(n, m % n);
}

char hexa(ll x) {
	if(x < 10) return '0' + x;
	else return 'A' + x - 10;
}

ll Ans[N];

int main() {
	open("fraction");
	in(n);
	fo(i, 1, n) {
		in(a), in(b);
		ll g = gcd(a, b);
		a /= g, b /= g;
		ll up = sqrt(b);
		ll tmp = b;
		fo(i, 2, up) if(tmp % i == 0) {
			A[++len] = i;
			while(tmp % i == 0 )tmp/=i;
		}
		if(tmp > 1) A[++len] = tmp;
		fo(i, 1, len) s.insert(A[i]);
		len =0 ;
	}
	
	
	sum = 1;
	set<ll>::iterator it;
	for(it = s.begin() ; it != s.end() ; ++it)sum = sum * (*it);
	
	ll cnt =0;
	while(check(sum)) {
		Ans[++cnt] = sum % 16;
		sum = sum / 16;
	}
	Ans[++cnt] = sum.val();
	
	fown(i, cnt, 1) pf("%c", hexa(Ans[i]));
	
	return 0;
}

O(\sqrt[2]{maxn}~*~n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值