纪中17日T2 2322. capacitor

2322. capacitor 

(File IO): input:capacitor.in output:capacitor.out

题目描述

输入

输出

样例输入

样例输出

数据范围限制

Solution

注意这句话

温暖了这道题目~

首先我要解释一下并联和串联的意义:

将$frac ab$与1串联

$mathsf{frac {1}{frac ba + frac 11}}$

$=frac{1}{frac{a+b}{a}}$

$=frac{a}{a+b}$

将$frac ab$与1并联

$ frac ab + 1$

$=frac {a+b} {a} $

所以,经过一次操作后,实际上只是把分子加上了分母或者是把分母加上了分子!

接下来

对于任何一个分数$frac ab$,首先将其化成最简分数(约分),再提取整数部分,最后再代回$frac ab$

倒过来推导之前的过程:将a,b中大的数减去小的数,直到两者皆为1

于是,我竟然有4个点时间超限了!

(下了个数据)

500
1 399679155189143654
1 410370078528392874
1 339653269813392707
1 576530157429321720
1 965741222600829828
1 424185399245015572
1 432555277044064202
1 227038592437239613
1 645326367328146934
1 812040302868109557
1 254672559822995754
1 777810836387141629
1 932184458600829894
1 770858965193507925
1 588847170170244972
1 479576325626445120
1 121481029521872124
1 605105712228419901
1 630952467219952791
…………
某个数据的一部分

好厉(wei)(suo)

再优化

我优化了两个地方:

求gcd使用二进制法以及卡常(可无视)

以及

减少相减循环的次数

当a,b反复相减时,总有一个数会先变成1(假设是a),然后b又要执行b次运算,每次仅仅是把b-=1,ans++……这个地方一定可以优化!

直接在a,b有一者减成1时跳出循环(假设是a)

本来还有b次循环,那么这时的答案就会比正确答案少b

所以,最后再把ans+=a*b即可

(上面的式子对a=1或b=1都适用)

Code

#include<iostream>
#include<cstdio>
using namespace std;
long long a,b,ans,t,g,n;
long long gcd(long long a,long long b)
{
    if(!b) return a;
    if(!(a|0)&&!(b|0)) return 2*gcd(a>>1,b>>1);
    if((!(a|0))&&(b|0)) return gcd(a,b>>1);
    if(!(a|0)&&!(b|0)) return gcd(a>>1,b);
    return gcd(b,a%b);
}
int main()
{
//    freopen("capacitor.in","r",stdin);
//    freopen("capacitor.out","w",stdout);
    cin>>t;
    while(t--)
    {
        scanf("%lld%lld",&a,&b);
        ans=0;
        g=gcd(a,b);
        a/=g;b/=g;
        n=a/b;
        if(a>b) swap(a,b);
        while(a!=1&&b!=1)
        {
            ans++;
            b-=a;
            if(a>b) swap(a,b);//a<b
        }
        cout<<ans+a*b<<endl;
    }
    return 0;
}

End

这道题我会,还是WA了!!!

今天又是爆0的一天啊……

原文地址:https://www.cnblogs.com/send-off-a-friend/p/11368037.html