求一个数的排列的gcd
Finding gcd of permutations of a Number
这是问题的链接:
http://www.spoj.com/problems/GCD/
考虑自然数N的十进制表示。找出所有数字的最大公约数(GCD),这些数字可以通过排列给定数字中的数字来获得。允许前导零。
我采用了以下方法:https://math.stackexchange.com/a/22453
首先,如果所有数字都相同,那么只有一个数字,那就是GCD。如前所述,如果3或9是一个排列的因子,那么它将是所有排列的因子。否则,想象一下,当1和10位数不同时,只交换它们。这两者的GCD必须除以100a+10b+c−100a+10c+b=9(b−c),其中b和c是个位数。为了使所有数字的GCD具有因子2,所有数字必须是偶数。对于因子为4的GCD,所有数字必须为0、4或8,对于8,它们必须为0或8。5和7也是如此。最后,如果所有数字都是0、3、6或9,则GCD将为27,并且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。我似乎找不到任何可能出错的边缘案例。
请告诉我哪里错了。感谢:)
首先,如果所有数字都相同,那么只有一个数字,那就是GCD。
你不能处理这个(第一个)案例
因此,对于您的代码,所有11
、111
、44
都给出了错误的答案。
[..]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;
}
相关文章:
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么不;名字在地图上是按顺序排列的吗
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 按对象的特定方法按升序排列的C++优先级队列
- 找到具有最多子串栅栏的字符串排列
- 重新排列单线以形成闭合多边形?
- 查找 GCD:并非所有控制路径都返回值
- 在数组中输入 n 个整数的列表,并以类似于钟摆来回移动的方式排列它们. 输入-1 3 2 5 4,输出5 3 1 2 4
- 输入的 C++ 排列
- 公共/私有/受保护是否会更改内存中结构的排列?
- 如何在 C/C++ 中生成具有 n 组 5 个值(重复项)的所有可能排列的矩阵
- 在向量C++中排列奇数和偶数
- 如何进行排列?
- 矩阵行求和与 RowMajor 和 ColMajor 数据排列的奇怪性能差异
- 在 CPP 中打印具有重复项的选定长度字符的所有排列
- 为什么 std::gcd/lcm 返回 std::common_type_t<M, N> 而不是 auto?
- 如何在不使用 C++ 中的数组或函数的情况下查找 N 位数字的所有排列
- 调用参数排列不变函数 f(i++, i++)
- 以 C++ 为单位具有输出限制的排列
- 求一个数的排列的gcd