校赛Round2 1006 Capacitance(电容)

Problem Description

Ivy_End最近得到了一大堆电容,他希望通过使用这些电容通过串联或者并联来得到一个任意电容的电路。

关于电容的串并联计算方法如下:
1. 假设两个电容为C1、C2,则串联后的电容为 C = (C1 * C2) / (C1 + C2)
2. 假设两个电容为C1、C2,则并联后的电容为 C = C1 + C2

综上所述,电容的串联计算法则与电阻的并联计算法则相同;电容的并联计算法则和电阻的并联计算法则相同。

现在Ivy_End获得了一大堆1pF的电容,他希望用他们来获得一个电容为C的电容,请问最少需要多少个1pF的电容。

Input

多组样例(>=20,000),每组一行。
输入格式U D(U,D<=1,000,000,000,000,000,000),表示总电容C = U / D,表示希望获得的电容大小。

Output

每组一行。
输出格式为 Case #T: N,其中T、N分别表示样例组数、最少需要的电容数。

Sample Input

1 1
1 2
1 3

Sample Output

Case #1: 1
Case #2: 2
Case #3: 3

Author

Ivy_End


我的想法:

U>D,则U/D的整数部分直接用1pF并联就好了。

再考虑真分数,易得1/n的电容最少可由n个1pF的电容串联获得。每个真分数最少可以看成若干个1/i的电容并联获得(即数值相加)

例如:

3/5=1/2+1/10;

7/8=1/2+1/4+1/8;

2/5=1/5+1/5.

这里一开始需要对U%=D后的值和D/2进行比较,如果U/D大于1/2那么要选一个1/2的电容。而且接下来选的电容值的分母一定得是D的因子,这样才能保证整体数量最少。

例如:

4/5=1/2+3/10=1/2+1/5+1/10;这时总个数是2+5+10=17个。

4/5=1/2+3/10=1/2+1/4+1/20;这时总个数是2+4+20=26个,显然大了很多。

其实这是因为只有选了D的因子这样在接下来选的时候才不会使分母大于D。

可以看一下下面的代码。

#include <stdio.h>
long long gcd(long long m, long long n)
{
	long long t;
	while (m)
	{
		t = n%m;
		n = m;
		m = t;
	}
	return n;
}
int main()
{
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
	long long u, d, ans, cases = 0,i,t;
	while (~scanf("%I64d%I64d", &u, &d))
	{
		t = gcd(u, d);
		u /= t;
		d /= t;
		ans = 0;
		ans += u / d;
		u = u%d;
		if (u == 0)
		{
			printf("Case #%I64d: %I64d\n", ++cases, ans);
			continue;
		}
		else
		{
			if (u - d / 2 > 0)
			{
				ans += 2;
				u = u * 2 - d;
				d = d * 2;
			}
			for (i = 3;u&&i<d;i++)
			{
				if (d%i==0&&u - d / i >=0)
				{
					ans += i;
					u -= d / i;
				}
			}
			if(u) ans += u*d;
			printf("Case #%I64d: %I64d\n", ++cases, ans);
		}
	}
	return 0;
}


然而,这并没有什么用!因为TLE了!

我把约分的步骤去掉又提交了一次,依然是TLE!

然后看了给的题解,没想到用到了这个结论:

使用1pF的电容得到A/BpF的电容的最少个数与得到B/ApF的最少个数相同。

说得好像很有道理,我竟无言以对,跪了!

那就一直循环迭代直到分子为0退出就好了!

#include <stdio.h>
int main()
{
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
	long long u, d, ans, cases = 0,t;
	while (~scanf("%I64d%I64d", &u, &d))
	{
		ans = 0;
		while (d)
		{
			ans += u / d;
			t = u%d;
			u = d;
			d = t;
		}
		printf("Case #%I64d: %I64d\n", ++cases, ans);
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值