【发布时间】: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