алгоритм — Эффективный подсчет делителей числа в O (n ^ (1/3)) в переполнении стека

Я нашел эффективный алгоритм для подсчета делителей числа в O (n ^ (1/3)) здесь: https://codeforces.com/blog/entry/22317

Я реализовал алгоритм в коде ниже. Но это не работает должным образом.

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define pb push_back
#define endl "\n"#define pi 2*acos(0)

#define debug(s) cout << #s << " = " << s << endl
#define all(v) (v).begin(), (v).end()
#define mem(a, val) memset(a, val, sizeof a)

vector<int> prime(10000000, 1); // array size is 10^7
void sieve(ll n){
prime[0]=prime[1]=0;
for(ll i=2; i<=sqrt(n); i++){
if(prime[i]==1){
for(ll j=2; i*j<=n; j++) prime[i*j]=0;
}
}
}
bool isPrime(ll n){
if(n<2) return false;
return prime[n];
}

vector<int> primeTable;
ll numberOfDivisors(ll n){
for(int i=0; i<1000000; i++){
if(prime[i]==1) primeTable.pb(i);
}
ll ans=1;
for(int i=0; ; i++){
if(primeTable[i]*primeTable[i]*primeTable[i]>n) break;
ll cnt=1;
while(n%primeTable[i]==0){
n=n/primeTable[i];
cnt++;
}
ans*=cnt;
}
double sqn=sqrt(n);
if(isPrime(n)) ans*=2;
else if((sqn-floor(sqn))==0 and isPrime((ll)sqn)) ans*=3;
else if(n!=1) ans*=4;

return ans;
}

int main()
{
ios_base::sync_with_stdio(false);cin.tie(NULL);
ll n;
cin >> n;
ll N=cbrt(n);
sieve(N);
cout << numberOfDivisors(n) << endl;

return 0;
}

то есть для 15 он возвращает 2 (должно быть 4), для 100 он возвращает 6 (должен быть 9), для 999 он возвращает 8 (что правильно), но снова для 9999 он возвращает 6 (должно быть 12). Я думаю, что что-то не так между строк 42 и 45. Но я не могу найти ошибку. Пожалуйста, помогите мне найти ошибку.

0

Решение

Вы устанавливаете начальное значение prime здесь 1 vector<int> prime(10000000, 1), Затем обновите значение prime вплоть до n в seive(ll n) функция. Таким образом, для n+1 в 10000000 prime значение останется 1. В вашей основной функции вы запустили sieve(N) за ll N=cbrt(n), По этой причине ваш isPrime(n) неверно, потому что n может быть больше, чем N=cbrt(n), Исправьте, что ваш код подходит.

Из сообщения в блоге я понимаю, что этот алгоритм предназначен для поиска факторов длинного целого числа. Они также упоминают, что для проверки первичности используют Миллера Рабина. Как вы проверяете isPrime(n) не будет работать для большого целого числа.

Также обновите эту часть (изменить 1000000 в cbrt(n)):

ll numberOfDivisors(ll n){
for(int i=0; i<1000000; i++){
if(prime[i]==1) primeTable.pb(i);
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]