【问题标题】:Finding gcd of permutations of a Number查找数字排列的 gcd
【发布时间】:2014-09-06 09:13:03
【问题描述】:

这里是问题的链接:

http://www.spoj.com/problems/GCD/

考虑自然数 N 的十进制表示。 通过排列给定数字中的数字,找到所有数字的最大公约数 (GCD)。允许使用前导零。

我采用了以下方法: https://math.stackexchange.com/a/22453

首先,如果所有数字都相同,则只有一个数字,即 GCD。如前所述,如果 3 或 9 是一个排列的一个因数,那么它将是所有排列的一个因数。否则,想象一下当它们不同时只交换个位和十位。这两者的 GCD 必须除以 100a+10b+c−100a+10c+b=9(b−c) 其中 b 和 c 是个位数。为了使所有数字的 GCD 具有因子 2,所有数字必须是偶数。对于 GCD 的因子 4,所有数字必须是 0、4 或 8,对于 8,它们必须是 0 或 8。5 和 7 也是如此。最后,如果所有数字都是 0,则 GCD 将为 27, 3,6 或 9 和 27 除以一个排列,如果所有数字都是 0 或 9,则 81 和 81 除以一个排列。你能证明最后一个断言吗?

我的解决方案: http://ideone.com/VMUb6w

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<string>



using namespace std;

int rem(string str, int a){
    if (str.empty())
    {
        return 0;
    }
    int temp = (str[str.length() - 1] - '0') % a;
    int temp2 = 10 % a;
    str.erase(str.length() - 1);
    int temp3 = (rem(str, a)*temp2) % a;
    return (temp3 + temp) % a;
}


int gcdf(int a, int b)
{
    return b ? gcdf(b, a%b) : a;
}


int main(){
    string str;
    while (cin >> str)
    {

    size_t l = str.length();
    vector<int> digit;
    int sum = 0;
    int frequency[9];
    for (int i = 0; i<9; i++)
        frequency[i] = 0;
    int zero_sum = 0;
    for (size_t i = 0; i < l; i++)
    {
        if (str.at(i) != '0')
        {
            frequency[str.at(i) - '1']++;
            sum += str.at(i) - '0';
        }
        else
        {
            zero_sum++;
        }
    }

    for (size_t i = 0; i < 9; i++)
    {
        if (frequency[i])
        {
            digit.push_back(i + 1);
        }
    }
    int gcds = 0, gcd = 1;
    for (size_t i = 0; i < digit.size(); i++)
    {
        gcds = gcdf(digit[i], gcds);
    }
    if (gcdf(3, gcds) == 1)
    {
        gcd *= gcds;
    }
    if (gcds == 6)
    {
        gcd *= 2;
    }
    if ((rem(str, 81) == 0) && (gcdf(gcds, 3) == 3))
    {
        gcd *= 81;
    }
    else
    {
        if ((rem(str, 27) == 0) && (gcdf(gcds, 3) == 3))
        {
            gcd *= 27;
        }
        else
        {
            if (sum % 9 == 0)
            {
                gcd *= 9;
            }
            else
            {
                if (sum % 3 == 0)
                {
                    gcd *= 3;
                }
            }
        }
    }
    if((digit.size()==1)&&(zero_sum==0))
            cout<<str;
    else            
         cout << gcd << endl;


}
return 0;
}

但它正在给 WA。 我似乎找不到任何可能出错的边缘案例。

请告诉我我哪里错了。谢谢:)

【问题讨论】:

    标签: c++ math largenumber greatest-common-divisor


    【解决方案1】:

    首先,如果所有数字都相同,则只有一个数字,即 GCD。

    你不处理这个(第一个)案例

    因此,所有1111144 的代码都会给出错误的答案。

    [..] 81 如果所有数字都是 0 或 9 并且 81 除以一个排列。

    您的测试似乎是错误的:

    if ((rem(str, 81) == 0) && (gcdf(gcds, 3) == 3))
    

    你的意思是:

    if ((rem(str, 81) == 0) && (gcdf(gcds, 9) == 9))
    

    所以

    你有 3699 个不一致的结果的排列:

    27 for 3699, 3996, 6939, 6993, 9369, 9693, 9936
    81 for 3969, 6399, 9396, 9639, 9963.
    

    我要检查的实现(对于 int 数)是:

    int my_gcd(std::string str)
    {
        std::sort(str.begin(), str.end());
        std::string first = str;
        int gcd = atoi(first.c_str());
    
        while (std::next_permutation(str.begin(), str.end())) {
            gcd = gcdf(atoi(str.c_str()), gcd);
        }
        return gcd;
    }
    

    【讨论】:

    • 我已经按照你说的实现了。但我仍然得到错误的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-15
    • 1970-01-01
    • 2022-11-10
    • 2014-02-03
    相关资源
    最近更新 更多