[Codeforces 585C] Alice, Bob, Oranges and Apples (Stern-Brocot Tree + 更相减损法)

22 篇文章 0 订阅
15 篇文章 0 订阅

Codeforces - 585C

A和 B两个人玩一个游戏,开始时一共有 X 个橘子和 Y 个苹果
A先拿出一个橘子,B拿出一个苹果,然后进行若干次操作
每次一个人将所有的水果给另一个人,
然后再从袋子里拿出与之前等量的两种水果
最后袋子里的水果恰好被拿完,求构造一个满足条件的操作序列


如果知道 Stern-Brocot Tree 这个东西的话,
会发现整个游戏过程和它的构造过程是一样的

刚开始有 01 10 两个既约分数
其中分母代表橘子,分子代表苹果,第一个分数代表 A,第二个分数代表 B
然后每次将其中一个分数替换成两个分数的 mediant(中间值)
ab cd 的中间值为 a+cb+d
所以根据 Stern-Brocot Tree 的性质:
YX 要是上面的一个节点,必须满足 gcd(X,Y)=1
并且如果 gcd(X,Y)=1 ,那么 YX 一定是上面的一个节点
然后就顺着这个树去找节点就好了

如果 gcd(X,Y)1 ,那么就是 “Impossible”
如果 X>Y ,就顺着左儿子向下走,并且将分数换成 YXY ,同理 Y>X
那么这就是一个更相减损法了,同样可以用辗转相除法来优化
这样一来时间复杂度就是 (log(max(X,Y)))

#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <map>
#include <set>
#include <queue>
#include <bitset>
#include <string>
#include <complex>
using namespace std;
typedef pair<int,int> Pii;
typedef long long LL;
typedef unsigned long long ULL;
typedef double DBL;
typedef long double LDBL;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define SQR(a) ((a)*(a))
#define PCUT puts("\n----------")

LL GCD(LL a, LL b) {return b?GCD(b,a%b):a;}
LL X,Y;

int main()
{
    #ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt", "w", stdout);
    #endif

    while(~scanf("%lld%lld", &X, &Y))
    {
        if(GCD(X,Y)!=1) puts("Impossible");
        else
        {
            while(X>1 && Y>1)
            {
                if(X>Y)
                {
                    printf("%lldA", X/Y);
                    X -= X/Y*Y;
                }
                else
                {
                    printf("%lldB", Y/X);
                    Y -= Y/X*X;
                }
            }
            if(Y==1) printf("%lldA", X/Y-1);
            if(X==1) printf("%lldB", Y/X-1);
            puts("");
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值