本帖最后由 guosl 于 2022-10-14 21:35 编辑
思路同上,但上面的代码只把原数分成了两个部分,我们现在用递归进行完全分解。
答案:9857164023(耗时不到1秒)#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cmath>
#include <omp.h>
using namespace std;
char a[12] = "9876543210";
bool bContinue = true;
long long GCD(long long a, long long b) //求a,b的最大公因数
{
if (b == 0)
return a;
long long t = a % b;
while (t != 0)
{
a = b;
b = t;
t = a % b;
}
return b;
}
void fillbits(unsigned char *bs, long long k)
{
while (k > 0)
{
++bs[k % 10];
k /= 10;
}
}
bool chk(vector<long long> v)
{
if (v.size() == 1)
return false;
long long nUp;
if (v.size() == 2)
nUp = 99;
else if (v.size() > 2)
nUp = 9;
long long d = v[0];
for (int i = 1; i < (int)v.size(); ++i)
d = GCD(d, v[i]);
d = min(d, nUp);
for (int i = 2; i <= d; ++i)
{
if ((d % i) == 0)
{
unsigned char bs[10];
memset(bs, 0, sizeof(bs));
fillbits(bs, i);
for (int j = 0; j < (int)v.size(); ++j)
fillbits(bs, v[j] / i);
bool bSuccess = true;
for (int j = 0; j < 10; ++j)
{
if (bs[j] != 1)
{
bSuccess = false;
break;
}
}
if (bSuccess)
return true;
}
}
return false;
}
bool dfs(vector<long long> v, int k, char *b)
{
long long x = 0;
x = atoll(b + k);
vector<long long> v1 = v;
v1.push_back(x);
if (chk(v1))
return true;
v1.pop_back();
x = 0;
for (int i = k; i < 9; ++i)
{
x = 10 * x + int(b[i] - '0');
v1.push_back(x);
if (dfs(v1, i + 1, b))
return true;
v1.pop_back();
}
return false;
}
int main(void)
{
long long nMax = 0;
#pragma omp parallel shared(a,bContinue) reduction(max:nMax)
do
{
char a1[12];
#pragma omp critical
{
memcpy(a1, a, sizeof(a));
bContinue = prev_permutation(a, a + 10);
}
long long x = 0;
for (int i = 0; i < 9; ++i)
{
vector<long long> v;
x = 10 * x + int(a1[i] - '0');
v.push_back(x);
if (dfs(v, i + 1, a1))
{
nMax = max(nMax, atoll(a1));
#pragma omp critical
bContinue = false;
break;
}
}
}
while (bContinue);
cout << nMax << endl;
return 0;
}
|