Sicily 1732 Alice and Bob (二进制数的最大公约数)

链接: http://soj.me/1732

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description:

Alice is a beautiful and clever girl. Bob would like to play with Alice.

One day, Alice got a very big rectangle and wanted to divide it into small square pieces. Now comes a problem: if all pieces of small squares are of the same size, how big could the squares be? To Alice, it’s easy to solve the problem.
However, she was very busy, so she asked Bob to help her. You know Alice is such a lovely girl and of course Bob won’t refuse her request. But Bob is not so smart and he is especially weak in math. So he turns to you—a genius at programming.

Alice will inform Bob the length and width of the big rectangle, and Bob have to tell her the longest length for the small square. All of these numbers are in their binary representations.

Input:

The first line of the input is a positive integer. This is the number of the test cases followed. Each test case contains two integer L and W in their binary representation which tells you the length and width of the very big rectangle
(0<L, W<2^1000). There may be one or several spaces between these integers.

Output:

The output of the program should consist of one line of output for each test case. The output of each test case only contains the longest length for the small squares in its binary representation. No any redundant spaces are needed.

Sample Input:

2

100 1000

100 110

Sample Output:

100

10

分析:本题的大意就是给出两个数的二进制,求出他们的最大公约数,要用辗转相除法,由于本题的数据范围较大,需要使用高精度,如果简单套用使用辗转相除法gcd(n, m) = gcd(m, n%m)来求的话,那么就要完成一个高精度的除法的程序;

因为本题的输入和输出都使用二进制表示,所以可以使用以下方法来求最大公约数,(只需要用高精度的除法和以为运算);

本题采用的算法如下:

if a = 2p, b = 2q, then gcd(a, b) = 2*gcd(p, q);

if a = 2p, b = 2q+1, then gcd(a, b) = gcd(p, b);

if a = 2p+1, b = 2q, then gcd(a, b) = gcd(a, q);

if a = 2p+1, b = 2q+1, then gcd(a, b) = gcd(a-b, b) (assume a > b)

容易看出前三种情况都会导致其中一个整数减半,这样递减的速度是很快的,而且由于输入的是以二进制的方式输入,判断a, b的方式很简单;

那会不会连续调用第四种情况呢?答案是不会的,原因是:

当a = 2p+1, b = 2q+1时:

gcd(a, b) = gcd(a-b, b) = gcd(2(p-q), 2q+1) = gcd(p-q, 2q+1);

明显不可能出现连续调用第四种情况,时间复杂度也和标准的转转相除法一样是O(logn);

代码如下:

// Problem#: 1732
// Submission#: 2822044
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define MAXN 10005
#define RST(N)memset(N, 0, sizeof(N))
using namespace std;

typedef struct Node_
{
    int len;
    int v[MAXN];
}Node;

Node n, m;
int cas;
char str1[MAXN], str2[MAXN];

Node Tr(char *str)     //把字符串转换成数字形式;
{
    Node N;
    int len = strlen(str);
    N.len = len;
    for(int i=0; i<len; i++) N.v[i] = str[len-1-i]-‘0‘;
    return N;
}

bool CMP(Node n, Node m)  //比较两个数的大小;
{
    if(n.len < m.len) return true;
    if(n.len > m.len) return false;
    for(int i=n.len-1; i>=0; i--) {
        if(n.v[i] < m.v[i]) return true;
        else if(n.v[i] > m.v[i]) return false;
    }
    return false;
}

Node Minus(Node n, Node m)   //大整数高精度相减,注意是二进制相减;
{
    Node N = n;
    int borrow = 0, temp, i;   //borrow为借位;
    for(i=0; i<m.len; i++) {    //从低位减起;
        temp = N.v[i] - borrow - m.v[i];
        if(temp >= 0) {      //没有借位;
            borrow = 0, N.v[i] = temp;
        }else {
            borrow = 1, N.v[i] = temp + 2;
        }
    }
    for(; i<n.len; i++) {   //处理剩余位数;(假设n > m)
        temp = N.v[i] - borrow;
        if(temp >= 0) {
            borrow = 0, N.v[i] = temp;
        }else {
            borrow = 1, N.v[i] = temp + 2;
        }
    }
    while(N.len >= 1 && !N.v[N.len-1]) N.len--;
    return N;
}

Node div(Node n)  //大整数除2;由于是二进制,其本质就是移位;
{
    Node ret;
    ret.len = n.len-1;
    for(int i=0; i<ret.len; i++) ret.v[i] = n.v[i+1];
    return ret;
}

void gcd(Node n, Node m)   //求大整数的公约数;
{
    long cnt = 0;
    while(n.len && m.len) {
        if(n.v[0]) {
            if(m.v[0]) {   //a = 2p+1, b = 2q+1 情况
                if(CMP(n, m)) m = Minus(m, n);
                else n = Minus(n, m);
            }else m = div(m);   //a = 2p+1, b = 2q情况;
        }else {
            if(m.v[0]) n = div(n);   //a = 2p, b = 2q+1情况;
            else {
                n = div(n), m = div(m);   //a = 2p, b = 2q情况;
                cnt++;
            }
        }
    }
    if(m.len) for(int i=m.len-1; i>=0; i--) printf("%d", m.v[i]);   //输出结果;
    else for(int i=n.len-1; i>=0; i--) printf("%d", n.v[i]);
    while(cnt--) printf("0");
    printf("\n");
}

int main()
{
    scanf("%d", &cas);
    while(cas--) {
        scanf("%s %s", str1, str2);
        n = Tr(str1), m = Tr(str2);
        gcd(n, m);
    }
    return 0;
}                                

Sicily 1732 Alice and Bob (二进制数的最大公约数)

时间: 2024-08-28 00:33:22

Sicily 1732 Alice and Bob (二进制数的最大公约数)的相关文章

位运算 F Alice and Bob

题目传送门 1 /* 2 题意: 求(a0*x^(2^0)+1) * (a1 * x^(2^1)+1)*.......*(an-1 * x^(2^(n-1))+1) 式子中,x的p次方的系数 3 二进制位运算:p = 2 ^ i + 2 ^ j + 2 ^ k + ...,在二进制表示下就是1的出现 4 例如:10 的二进制 为1010,10 = 2^3 + 2^1 = 8 + 2,而且每一个二进制数都有相关的a[i],对p移位运算,累计取模就行了 5 */ 6 #include <cstdio

codeforces_346A Alice and Bob(数学)

题目链接:http://codeforces.com/problemset/problem/346/A 参考链接:http://blog.csdn.net/loy_184548/article/details/50174615 感受到数学在博弈论中的强大. 考虑最后终止状态的序列-无法取出任意两个数他们的差值不存在这个序列中:那么这必定是个首项等于公差的等差序列 而这个序列是 d 2d 3d....,因此可以通过a[1] a[2] a[3] ...的最大公约数得到 然后计算有几个数没在数组中,判

HDU4268 Alice and Bob 【贪心】

Alice and Bob Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2869    Accepted Submission(s): 926 Problem Description Alice and Bob's game never ends. Today, they introduce a new game. In this

博弈问题-Alice与Bob拿牌游戏

Description Bob and Alice play a game, and Bob will play first. Here is the rule of the game: 1) There are N stones at first; 2) Bob and Alice take turns to remove stones. Each time, they can remove p^k stones. p is prime number, such as 2, 3, 5, ...

Alice and Bob

Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Description It is so boring in the summer holiday, isn't it? So Alice and Bob have invented a new game to play. The rules are as follows. First, they get a se

HDU 4111 Alice and Bob (博弈)

Alice and Bob Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1799    Accepted Submission(s): 650 Problem Description Alice and Bob are very smart guys and they like to play all kinds of games i

HDU 4268 Alice and Bob(贪心+multiset)

HDU 4268 题意:Alice与Bob在玩卡片游戏,他们每人有n张卡片,若Alice的一张卡片长与宽都不小于Bob的一张卡片,则Bob的卡片就会被盖住,一张卡片只可以使用一次,且不可旋转求Alice最多可以盖住多少张Bob的卡片. 思路:记录两人卡片情况,并按照长度将两人卡片分别降序排序.遍历两人的卡片,将长度小于Alice的卡片长度的Bob卡片的宽度插入multiset中,在multiset中找到小于等于Alice卡片宽度的第一个数,将这个数给消去且答案+1.//贪心法自行发挥即可. co

HDU 4268 Alice and Bob(贪心+Multiset的应用)

 题意: Alice和Bob有n个长方形,有长度和宽度,一个矩形可以覆盖另一个矩形的条件的是,本身长度大于等于另一个矩形,且宽度大于等于另一个矩形,矩形不可旋转,问你Alice最多能覆盖Bob的几个矩形? 思路:贪心,先按照h将Alice和Bob的矩形排序,对于Alice的每个矩形,如果Bob的矩形的h小于Alice的h,将Bob的w插入到集合中. 然后,在集合中找到不大于Alice矩形d的最大的Bob的d,那么这样做肯定是最优的. #include<cstdio> #include<

ZOJ 3666 Alice and Bob (SG博弈)

题目: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3666 题意: 给一个有向图,然后A和B轮流移动棋子,棋子在每一个位置可以重叠,当某人不能走时,输! 问A和B谁赢 方法: 显然每一局游戏都是独立的,对每一局游戏异或即可 每一局游戏的结果可以用SG求,记忆化搜索之 1 int dfs(int x) 2 { 3 if (sg[x] != -1) return sg[x]; 4 bool vis[maxn]; 5 me