Я нашел эффективный алгоритм для подсчета делителей числа в 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. Но я не могу найти ошибку. Пожалуйста, помогите мне найти ошибку.
Вы устанавливаете начальное значение 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);
}
Других решений пока нет …