历届真题 循环小数【第十一届】【决赛】【研究生组】

题目如上。

这题我是肯定想不出来捏,因为它蕴涵一个可爱的数学知识(bushi。

 所有的小数可以表现为两种形式:

1.不循环小数:0.5 则可以转化为5 / 10的分数形式。

2.循环小数:0.333 则可以转化为333 / 999的分数形式。

那这题不就是迎刃而解了吗。

根据pq的位置把不循环小数和循环小数都找出来。

最后得到的就是不循环小数:x/10^(n),循环小数:y/(n个9).其中n是x和y对应的位数。

然后把这两个分数进行约分就好啦。

是不是以为很简单呢,对啊,我这么提交之后得了20分。

为啥呢,因为循环节在后面啊,前面的不循环部分还占了几个0呢!

例如 样例2 2 16 就是1/10 + 6 / (9 * 10);因为6是在第二位,所以得再除以一个10.

说不明白,大家体会一下。

代码如下:

因为数据范围是10位,我怕出现溢出的情况,就都用了long long类型的。

ll gcd(ll a, ll b){
	return b == 0 ? a : gcd(b, a % b);
}
int main(){
	ll p, q;
	cin>>p>>q;
	string xs;
	cin>>xs;
	ll bu = 0;  //不循环部分的分子 
	ll buc = 1; //不循环部分的分母,也就是10^n(n是不循环部分的位数) 
	ll xh = 0;  //循环节部分的分子 
	ll xhc = 0; //循环节部分的分母,也就是n个9 
//	ll zw = 1;  //占位,循环节未必从小数点后马上开始,
//所以得找出还需要除以10^n,但是其实和buc一样的,直接用buc 
//这个占位可以理解为本来是0.03,我们先转化为3/9,但是这不就相当于把0.3扩大了10倍吗,那就分母除以10 
	for(int i = 1; i < p; i++){
		bu *= 10;
		bu += xs[i - 1] - '0';
		buc = buc * 10;
	} 
//	cout<<bu<<" "<<buc<<endl;
	for(int i = p; i <= q; i++){
		xh *= 10;
		xh += xs[i - 1] - '0';
		xhc = xhc * 10 + 9;
	} 
	xhc *= buc;
//	cout<<xh<<" "<<xhc<<endl;
	ll fenzi = 0;
	ll fenmu = 0;
	ll g;
	if(bu && xh){
		fenzi = bu * xhc + buc * xh;
		fenmu = xhc * buc;
		g = gcd(fenzi, fenmu);
//		cout<<fenzi<<" "<<fenmu<<" "<<g<<endl;
	}else if(bu){
		fenzi = bu;
		fenmu = buc;
		g = gcd(bu, buc);
//		cout<<fenzi<<" "<<fenmu<<" "<<g<<endl;
	}else{
		fenzi = xh;
		fenmu = xhc;
		g = gcd(xh, xhc);
//		cout<<fenzi<<" "<<fenmu<<" "<<g<<endl;
	}
	printf("%lld %lld\n", fenzi / g, fenmu / g);
	return 0;
} 
//1 6
//142857

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值