【题解】HL模拟赛2022.09.29T1——电阻

题目

题目描述

Z Z Z 要进行物理实验,需要 T T T 个电阻,每个电阻所需要的电阻值都可以用一个分数进行表示。
但很不幸的是,物理实验室只有阻值为 1 1 1 的电阻和电阻可以忽略不计的导线,好在这些物品有无限多个。
于是小 Z Z Z 打算通过串并联的方式尝试构造自己所需要的每个电阻,对于每个电阻,小 Z Z Z 都会从一个阻值为 1 1 1 的电阻开始,每次在原有的电路基础上串联或者并联一个阻值为 1 1 1 的电阻,他想知道对于自己所需要的每个阻值,最少需要使用多少个阻值为 1 1 1 的电阻才能拼出来。

输入格式

第一行为一个正整数 T T T,表示数据组数,接下来 T T T 组数据,每组数据一行两个整数 A , B A,B A,B ,表示需要一个阻值为 A / B A/B A/B 的电阻。

输出格式

对每组数据输出一行一个非负整数,表示答案。

样例输入 #1

2
2 3
5 2

样例输出 #1

3
4

【样例解释】

第一组数据中,从一个阻值为 1 1 1 的电阻开始,并联一个阻值为 1 1 1 的电阻,再串联一个阻值为 1 1 1 的电阻即可。
第二组数据中,将两个阻值为 1 1 1 的电阻并联,再串联两个阻值为 1 1 1 的电阻。

【数据规模与约定】

本题一共 10 10 10 个测试点,每个测试点 10 10 10 分。

1 ∼ 3 1\sim 3 13 个测试点,满足 T , A , B ≤ 20 T,A,B≤20 T,A,B20

所有测试点均满足 1 ≤ T ≤ 1000 ; 1 ≤ A , B ≤ 1 0 18 1≤T ≤1000 ; 1 ≤ A,B ≤ 10^{18} 1T1000;1A,B1018

思路

题意大概就是用一些阴值为 1 1 1 的电阻,去串联或并联其余阴值为 1 1 1 的电阻,求出操作后最终值为 A B \frac{A}{B} BA 最少需要几个电阻。
我们设当前的阴值 Q P \frac{Q}{P} PQ,则串联一个阴值为 1 1 1 的电阻后,阴值会变为 Q + P P \frac{Q+P}{P} PQ+P,并联一个阴值为 1 1 1 的电阻后,阴值会变为 Q P + Q \frac{Q}{P+Q} P+QQ,可以发现要么操作一次后要么是分母加分子,要么是分子加分母。
而且我们还可以发现一个性质:我们记 f ( A B ) f(\frac{A}{B}) f(BA) 表示让阴值成为 A B \frac{A}{B} BA 所需的电阻数,则 f ( A B ) = f ( B A ) ( A > B ) f(\frac{A}{B})=f(\frac{B}{A})(A>B) f(BA)=f(AB)(A>B)
证明:我们假设 A A A B B B 满足上面的性质,则说明 f ( A B ) = f ( B A ) f(\frac{A}{B})=f(\frac{B}{A}) f(BA)=f(AB),那么 f ( A + B A ) = f ( B A ) + 1 f(\frac{A+B}{A})=f(\frac{B}{A})+1 f(AA+B)=f(AB)+1 f ( A A + B ) = f ( A B ) + 1 f(\frac{A}{A+B})=f(\frac{A}{B})+1 f(A+BA)=f(BA)+1,因为 f ( A B ) = f ( B A ) f(\frac{A}{B})=f(\frac{B}{A}) f(BA)=f(AB),所以 f ( A + B B ) = f ( A A + B ) f(\frac{A+B}{B})=f(\frac{A}{A+B}) f(BA+B)=f(A+BA)。而数归的起点是 A = 1 , B = 1 A=1,B=1 A=1,B=1
所以我么就可以得出我们的算法:

f ( A B ) = { B = 0        0 A ≥ B     ⌊ A B ⌋ + f ( A   m o d   B B ) A < B      f ( B A ) f(\frac{A}{B})=\begin{cases}B=0~~~~ ~~0\\A≥B~~~ \left \lfloor \frac{A}{B} \right \rfloor+f(\frac{A\bmod B}{B}) \\A<B~~~~ f(\frac{B}{A})\end{cases} f(BA)= B=0      0AB   BA+f(BAmodB)A<B    f(AB)

容易看出这是一个递归,即可实现。

代码

#include<bits/stdc++.h>
using namespace std;
#define R register
#define ri register int
#define int long long
#define ull unsigned long long
#define lid (id<<1)
#define rid (id<<1|1)
void swap(int &x,int &y){int t=x;x=y;y=t;}
inline int max(int x,int y){return x>y?x:y;}
inline int min(int x,int y){return x<y?x:y;}
const int N=2e5;
inline int read();
inline void write(int ans);
inline void put(int x,char c);
int T,a,b;
int get(int n,int m){
	if(m==0)
		return 0;
	if(n<m)
		return get(m,n);
	return n/m+get(n%m,m);
}
signed main(){
	T=read();
	while(T--){
		a=read(),b=read();
		int ss=__gcd(a,b);
		a/=ss;
		b/=ss;
		printf("%lld\n",get(a,b));
	}
	return 0;
}
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
inline void write(int x){if(x<0){putchar('-');x=-x;}if(x>9){write(x/10);}putchar(x % 10+'0');return;}
inline void put(int x,char c){write(x);putchar(c);return;}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值