Задача "Степень"
Дана задача:
Для того чтобы проверить, как её ученики умеют считать, Мария Ивановна каждый год задаёт им на дом одну и ту же задачу — для заданного натурального A найти минимальное натуральное N такое, что N в степени N (N, умноженное на себя N раз) делится на A. Необходимо написать программу, решающую эту задачу
1 ≤ A ≤ 10^9
Я написал такой код:
#include <iostream>
#include <vector>
#include <cmath>
#include <unordered_set>
using namespace std;
vector<int> decomp (int n)
{
vector<int> ans (0);
int d = 2;
while (d * d <= n)
{
if (n % d == 0)
{
ans.push_back(d);
n /= d;
}
else
d += 1;
}
if (n > 1)
ans.push_back(n);
return ans;
}
int main()
{
int x; cin >> x;
if (x == 1)
cout << 1;
else
{
vector<int> tmp = decomp(x);
unordered_set<int> s;
for (int el: tmp)
s.insert(el);
vector<int> a (0);
for (int el: s)
a.push_back(el);
int y = 1;
for (int i = 0; i < a.size(); i++)
y *= a[i];
if (y >= 29)
cout << y;
else
{
int k = 1; int n = k * y;
while ((int)pow(n, n) % x != 0)
{
n = k * y;
k += 1;
}
cout << n;
}
}
}
Но он выполняется слишком медленно. Помогите пожалуйста, как можно его оптимизировать?
Ответы (1 шт):
Автор решения: Harry
→ Ссылка
Ну, например, так:
#include <iostream>
#include <map>
using namespace std;
map<unsigned int, unsigned int> factor(unsigned int A)
{
map<unsigned int,unsigned int> m;
while(A%2 == 0) { m[2]++; A /= 2; };
for(unsigned int i = 3; i*i <= A; i += 2)
{
while(A%i == 0) { m[i]++; A /= i; };
}
if (A != 1) m[A]++;
return m;
}
int main(int argc, const char * argv[])
{
unsigned int A;
cin >> A;
if (A == 1) { cout << "1\n"; return 0; }
auto m = factor(A);
unsigned int p = 1;
unsigned int e = 0;
for(const auto& v: m)
{
p *= v.first;
if (v.second > e) e = v.second;
//cout << v.first << " ** " << v.second << endl;
}
if (p < e)
{
unsigned int N = ((e+p-1)/p)*p;
unsigned int M = p, k = 1;
while(M*k < e)
{
for(const auto& v: m)
{
if (v.second == e)
{
M *= v.first;
k++;
}
}
}
cout << ((M < N) ? M : N) << endl;
}
else cout << p << endl;
}