किसी दिए गए नंबर के विभाजकों की संख्या की गणना करने के लिए एल्गोरिदम


177

किसी दिए गए नंबर के विभाजकों की संख्या की गणना करने के लिए सबसे इष्टतम एल्गोरिदम (प्रदर्शन-वार) क्या होगा?

यदि आप स्यूडोकोड या कुछ उदाहरण के लिए एक लिंक प्रदान कर सकते हैं तो यह बहुत अच्छा होगा।

संपादित करें: सभी उत्तर बहुत उपयोगी रहे हैं, धन्यवाद। मैं एटकिन की छलनी को लागू कर रहा हूं और फिर जोनाथन लेफ्लर ने संकेत दिया है, मैं उसी तरह का उपयोग करने जा रहा हूं। जस्टिन बोज़ोनियर द्वारा पोस्ट किए गए लिंक में आगे की जानकारी है कि मैं क्या चाहता था।


कारकों की संख्या के साथ आने वाले आपके अवशेषों को देखते हुए अस्पष्ट है। मैं अनुमान लगा रहा हूं कि आप गैर-अद्वितीय प्राइम डिविजर्स की संख्या की तलाश कर रहे हैं क्योंकि अगर आप नहीं चाहते कि मैं कोड लिखूं तो हमेशा 1 वापस करने के लिए एक प्रोग्राम लिखो अगर फैक्टर की संख्या एक है और 2 अगर यह कुछ और है। 0 में बदलाव की जरूरत हो सकती है ...
जस्टिन बोजोनियर

@ भास्कर: क्या मूल्यों की एक श्रेणी है जिसके लिए आपको विभाजकों की आवश्यकता है। कारकों की गणना करने के कई तरीके हैं, और प्रत्येक विधि एक विशेष श्रेणी के लिए बेहतर है।
एंडी टर्नर

2
यहाँ एक संबंधित रोचक समस्या है projecteuler.net/problem=12
daniloquio

1
संपादित विकिपीडिया लेख से भी एटकिन की भोली छलनी कभी भी एक अधिकतम पहिया की तुलना में तेज नहीं होगी। भारी अव्यवहारिक सीमा तक Eratosthenes की चलनी, और पृष्ठ खंडित संस्करण भी SoE के अधिक पक्ष में हैं (SoE primesieve बनाम SoA Primegen के रूप में देखें) एटकिन के साथी बर्नस्टीन द्वारा लागू किया गया। यह सामान्य गलत इंटरनेट ज्ञान है कि उनके अध्ययन ने एसओए को तेजी से साबित किया, लेकिन उन्होंने इसे साबित करने के लिए कृत्रिम रूप से उपयोग किए गए एसओई के अनुकूलन को सीमित कर दिया। आगे की व्याख्या के लिए मेरे एसओए का जवाब देखें
गॉर्डनबूड

जवाबों:


78

दिमित्री सही है कि आप चाहते हैं कि एटिनी की छलनी प्रधान सूची उत्पन्न करे लेकिन मुझे विश्वास नहीं है कि पूरे मुद्दे का ध्यान रखता है। अब जब आपके पास उन primes की एक सूची है, तो आपको यह देखना होगा कि उन primes में से कितने विभाजक के रूप में कार्य करते हैं (और कितनी बार)।

एल्गो के लिए कुछ अजगर यहां देखें और "विषय: गणित - विभाजक एल्गोरिथ्म" की खोज करें। हालाँकि उन्हें वापस करने के बजाय सूची में मौजूद वस्तुओं की संख्या गिनें।

यहाँ एक डॉ। मठ है जो बताता है कि आपको गणितीय रूप से क्या करने की आवश्यकता है।

अनिवार्य रूप से यह उबलता है यदि आपका नंबर nहै:
n = a^x * b^y * c^z
(जहां ए, बी, और सी एन के प्राइम डिविजर्स हैं और एक्स, वाई, और जेड उस समय की संख्या है जिसे डिविज़र दोहराया जाता है) तो सभी डिवोर्स की कुल संख्या है:
(x + 1) * (y + 1) * (z + 1)

संपादित करें: बीटीडब्लू, ए, बी, सी, आदि खोजने के लिए आप एक लालची अहंकार को क्या मात्रा में करना चाहते हैं अगर मैं इसे सही ढंग से समझ रहा हूं। अपने सबसे बड़े प्राइम डिविज़र के साथ शुरू करें और इसे अपने आप से तब तक गुणा करें जब तक कि एक और गुणा संख्या n से अधिक न हो जाए। फिर अगले निम्नतम कारक पर जाएं और पिछले प्राइम ^ की संख्या को वर्तमान प्राइम से गुणा किया गया और प्राइम द्वारा गुणा करते रहें जब तक कि अगला n से अधिक न हो जाए ... आदि उस समय की संख्या पर नज़र रखें, जिसे आप गुणा करते हैं। भाजक एक साथ और उन संख्याओं को ऊपर दिए गए सूत्र में लागू करते हैं।

मेरे अहंकार वर्णन के बारे में 100% निश्चित नहीं है लेकिन अगर ऐसा नहीं है तो यह कुछ इसी तरह का है।


1
यदि आप बड़ी संख्या में फैक्टरिंग कर रहे हैं, तो आप प्राइम लिस्ट को देखना भी नहीं चाहेंगे । आप जितनी जल्दी हो सके संभावनाओं की पूरी श्रृंखला को खत्म करना चाहते हैं! अधिक के लिए मेरा जवाब देखें।
user11318

मुझे एहसास हुआ कि यह 2 साल पहले था, लेकिन आपका अजगर अहंकार लिंक टूट गया है, यह जानने के लिए कि यह अब कहां मौजूद है?
जेबी

2
तो n = (a^x * b^y * c^z)-(x + 1) * (y + 1) * (z + 1)नियम है
SIslam

1
जैसा @ शशांक कहते हैं, "EDIT:" अनुभाग में एल्गोरिथ्म गलत है: मान लीजिए n = 45 = 3 * 3 * 5। सबसे बड़ा प्रधान भाजक 5 है, लेकिन इसे अपने आप से गुणा करना जब तक यह n से अधिक न हो जाए एल्गोरिदम से यह रिपोर्ट होगी कि इसमें कारक 5 की 2 प्रतियां हैं (5 * 5 = 25 <45 के बाद से)।
j_random_hacker

1
'सिवई ऑफ एटकिन' में सबसे अच्छे रूप में O (N / log (log (N))) की रनटाइम जटिलता है । ब्रूट-बल 1 से सभी संभावित विभाजकों की जाँच कर रहा है ... Sqrt (n) में O (Sqrt (N)) की रनटाइम जटिलता है जो अब तक बेहतर है। इस उत्तर को कैसे स्वीकार किया गया है?
le_m

47

वहाँ एक हैं बहुत कुछ एटकिन की चलनी से फैक्टरिंग के लिए और अधिक तकनीक। उदाहरण के लिए मान लें कि हम 5893 को फैक्टर करना चाहते हैं। वैसे इसका स्क्वैयर 76.76 है ... अब हम वर्गों के उत्पाद के रूप में 5893 लिखने की कोशिश करेंगे। वेल (77 * 77 - 5893) = 36 जो 6 वर्ग है, इसलिए 5893 = 77 * 77 - 6 * 6 = (77 + 6) (77-6) = 83 * 71 है। अगर वह काम नहीं किया होता तो हम देखते थे कि 78 * 78 - 5893 एक पूर्ण वर्ग था या नहीं। और इसी तरह। इस तकनीक से आप व्यक्तिगत अपराधों के परीक्षण की तुलना में n के वर्गमूल के निकट कारकों के लिए जल्दी से परीक्षण कर सकते हैं। यदि आप एक छलनी के साथ बड़े अपराधों को खारिज करने के लिए इस तकनीक को जोड़ते हैं, तो आपके पास अकेले छलनी की तुलना में बहुत बेहतर फैक्टरिंग विधि होगी।

और यह बड़ी संख्या में तकनीकों में से एक है जिसे विकसित किया गया है। यह काफी सरल है। अण्डाकार वक्रों के आधार पर फैक्टरिंग तकनीकों को समझने के लिए आपको सीखने, कहने, पर्याप्त संख्या सिद्धांत के लिए एक लंबा समय लगेगा। (मुझे पता है कि वे मौजूद हैं। मैं उन्हें नहीं समझता।)

इसलिए जब तक आप छोटे पूर्णांक के साथ काम नहीं कर रहे हैं, मैं खुद उस समस्या को हल करने की कोशिश नहीं करूंगा। इसके बजाय मैं PARI पुस्तकालय की तरह कुछ का उपयोग करने का एक तरीका खोजने की कोशिश करूंगा जिसमें पहले से ही एक अत्यधिक कुशल समाधान लागू हो। इसके साथ मैं लगभग 405 नंबर 124321342332143213122323434312213424231341 जैसे यादृच्छिक अंकों को लिख सकता हूं। (इसका कारक, अगर आपने सोचा हो, तो 29 * 439 * 1321 * 157907 * 284749 * 33843676813 * 4857795469949 है। मुझे पूरा विश्वास है कि इसने एटकिन की छलनी का उपयोग करके यह पता नहीं लगाया ...)


1
आप तकनीक बहुत चतुर हैं, लेकिन यह मुझे नहीं बताता कि संख्या के कितने कारक हैं, क्या यह है?
स्केयर

23
एक बार जब आपके पास मुख्य कारक होता है, तो यह पता लगाना कि कितने कारक हैं, सीधा है। मान लीजिए कि प्रमुख कारक p1, P2, ..., pk हैं और इन्हें m1, m2, ..., mk बार दोहराया जाता है। फिर (1 + एम 1) (1 + एम 2) ... (1 + एमके) कारक हैं।
user11318

एक दिलचस्प छलनी द्विघात चलनी है । यह संख्या सिद्धांत का उपयोग करता है - द्विघात बधाई और कुछ रैखिक बीजगणित। मैंने विश्वविद्यालय में 2 वर्ष की संख्या सिद्धांत पाठ्यक्रम में इसका उपयोग करने के लिए पर्याप्त सीखा।
टान्नर

33

@Yasky

आपके विभाजक कार्य में एक बग है कि यह सही वर्गों के लिए सही ढंग से काम नहीं करता है।

प्रयत्न:

int divisors(int x) {
    int limit = x;
    int numberOfDivisors = 0;

    if (x == 1) return 1;

    for (int i = 1; i < limit; ++i) {
        if (x % i == 0) {
            limit = x / i;
            if (limit != i) {
                numberOfDivisors++;
            }
            numberOfDivisors++;
        }
    }

    return numberOfDivisors;
}

6
जब (x% i) शून्य से भाग देने पर I = 0 नहीं होगा? मैं = 1. चाहिए?
21

@ श्रु 0 की जाँच वैसे भी व्यर्थ है क्योंकि 0 किसी संख्या का कारक नहीं है।
EJoshuaS -

29

मैं असहमत हूं कि एटकिन की छलनी जाने का रास्ता है, क्योंकि यह आसानी से [1, n] में हर संख्या की जांच करने में अधिक समय लगा सकता है क्योंकि यह विभाजन से संख्या को कम करने के लिए होगा।

यहां कुछ कोड दिए गए हैं, हालांकि थोड़ा हैकर, आमतौर पर बहुत तेज है:

import operator
# A slightly efficient superset of primes.
def PrimesPlus():
  yield 2
  yield 3
  i = 5
  while True:
    yield i
    if i % 6 == 1:
      i += 2
    i += 2
# Returns a dict d with n = product p ^ d[p]
def GetPrimeDecomp(n):
  d = {}
  primes = PrimesPlus()
  for p in primes:
    while n % p == 0:
      n /= p
      d[p] = d.setdefault(p, 0) + 1
    if n == 1:
      return d
def NumberOfDivisors(n):
  d = GetPrimeDecomp(n)
  powers_plus = map(lambda x: x+1, d.values())
  return reduce(operator.mul, powers_plus, 1)

ps कि इस समस्या को हल करने के लिए अजगर कोड काम कर रहा है।


11

यहाँ एक सीधा आगे O (sqrt (n)) एल्गोरिदम है। मैंने प्रोजेक्ट यूलर को हल करने के लिए इसका उपयोग किया

def divisors(n):
    count = 2  # accounts for 'n' and '1'
    i = 2
    while i ** 2 < n:
        if n % i == 0:
            count += 2
        i += 1
    if i ** 2 == n:
        count += 1
    return count

लेकिन आप हमेशा 2 से गिनती क्यों बढ़ाते हैं? ... क्या कोई प्रमेय है जिसे आपने लागू किया है?
समरकोड

3
क्योंकि आप sqrt (n) तक ही चुनाव लड़ रहे हैं। उदाहरण के लिए: यदि आप 36 के लिए सभी भाजक खोजने की कोशिश कर रहे हैं - तो आप 2 से 6 तक गिनेंगे। आप जानते हैं कि 1 और 36,2 & 18, 3 और 12, 4 और 9, 6,6 सभी भाजक हैं और वे जोड़े में आते हैं।
एंटनी थॉमस

2
बहुत बहुत धन्यवाद एंथोनी, मुझे अब समझ में आया: डी! एक छोटा सा परिशिष्ट: मुझे लगता है कि इसे अलग से sqrt (n) मान का व्यवहार करना चाहिए क्योंकि अभी के लिए इसे एक के बजाय दो बार ध्यान में रखना चाहिए, मुझे लगता है
SummerCode

जबकि O (sqrt (n)) बहुत बुरा नहीं है, यह इष्टतम नहीं है। अभाज्य कारक विघटन की गणना बहुत तेजी से की जा सकती है और विभाजकों की संख्या की गणना करने के लिए पर्याप्त है।
le_m

प्रत्येक पुनरावृत्ति पर, आपको i² की गणना करनी होगी, क्या मैं erationn (केवल एक बार गणना की गई) के साथ तुलना करना अधिक तेज़ नहीं होगा?
युकुएल

10

यह दिलचस्प प्रश्न जितना दिखता है, उससे कहीं अधिक कठिन है, और इसका उत्तर नहीं दिया गया है। प्रश्न को 2 बहुत भिन्न प्रश्नों में विभाजित किया जा सकता है।

1 दिया गया N, N के प्रमुख कारकों की सूची L को खोजें

2 एल, अद्वितीय संयोजनों की संख्या की गणना करें

मेरे द्वारा अब तक देखे गए सभी उत्तर # 1 का उल्लेख करते हैं और यह उल्लेख करने में विफल हैं कि यह भारी संख्या के लिए ट्रैक्टेबल नहीं है। मध्यम आकार के एन के लिए, यहां तक ​​कि 64-बिट संख्याओं के लिए, यह आसान है; विशाल एन के लिए, फैक्टरिंग समस्या "हमेशा के लिए" ले सकती है। सार्वजनिक कुंजी एन्क्रिप्शन इस पर निर्भर करता है।

प्रश्न # 2 पर अधिक चर्चा की आवश्यकता है। यदि L में केवल अनन्य संख्याएँ हैं, तो n वस्तुओं से k ऑब्जेक्ट चुनने के लिए संयोजन सूत्र का उपयोग करके यह एक सरल गणना है। दरअसल, आपको k को 1 से लेकर साइज़ोफ़ (L) तक बदलते हुए सूत्र को लागू करने से परिणाम प्राप्त करने की आवश्यकता है। हालांकि, एल में आमतौर पर कई अपराधों की कई घटनाएं होंगी। उदाहरण के लिए, L = {2,2,2,3,3,5} N = 360 का कारक है। अब यह समस्या काफी कठिन है!

# 2 को पुनर्स्थापित करना, दिए गए संग्रह C में k आइटम, जैसे कि आइटम में 'डुप्लिकेट, और आइटम b में b' डुप्लिकेट हैं, आदि 1 से k-1 आइटम के कितने अनूठे संयोजन हैं? उदाहरण के लिए, {2}, {2,2}, {2,2,2}, {2,3}, {2,2,3,3} प्रत्येक को एक बार और केवल एक बार L = {2,2 होना चाहिए , 2,3,3,5}। प्रत्येक ऐसा अनूठा उप-संग्रह, उप-संग्रह में आइटमों को गुणा करके एन का एक अनूठा विभाजक है।


यहाँ बहुत 2. के लिए इसी तरह एक समस्या के लिए कुछ छद्म कोड का कोई लिंक है answers.google.com/answers/threadview/id/392914.html
mR_fr0g

3
प्रश्न # 2 में एक प्रसिद्ध समाधान है। {P_i, k_i} के एक गुणन के लिए जहां p_iएक संख्या का k_iगुणन गुणनखंड होता है, उस संख्या के विभाजकों की कुल संख्या होती है (k_1+1)*(k_2+1)*...*(k_n+1)। मुझे लगता है कि आप इसे अब तक जानते हैं लेकिन मैं इस लाभ के लिए लिखता हूं अगर यहां एक यादृच्छिक पाठक।
नेस

9

आपके प्रश्न का उत्तर पूर्णांक के आकार पर बहुत निर्भर करता है। छोटी संख्या के लिए तरीके, उदाहरण के लिए कम तो 100 बिट, और संख्या के लिए ~ 1000 बिट (जैसे कि क्रिप्टोग्राफी में उपयोग किया जाता है) पूरी तरह से अलग हैं।


6

बस एक पंक्ति
मैंने आपके प्रश्न के बारे में बहुत सावधानी से सोचा है और मैंने एक अत्यधिक कुशल और प्रदर्शनकारी कोड लिखने की कोशिश की है, स्क्रीन पर दिए गए नंबर के सभी विभाजकों को प्रिंट करने के लिए हमें कोड की सिर्फ एक पंक्ति की आवश्यकता है! (gcc के माध्यम से संकलन करते समय विकल्प -std = c99 का उपयोग करें)

for(int i=1,n=9;((!(n%i)) && printf("%d is a divisor of %d\n",i,n)) || i<=(n/2);i++);//n is your number

दिव्यांगों की संख्या ज्ञात करने के लिए आप निम्नलिखित बहुत तेज़ कार्य (1 और 2 को छोड़कर सभी पूर्णांक संख्या के लिए सही ढंग से काम कर सकते हैं) का उपयोग कर सकते हैं

int number_of_divisors(int n)
{
    int counter,i;
    for(counter=0,i=1;(!(n%i) && (counter++)) || i<=(n/2);i++);
    return counter;
}

या यदि आप दिए गए नंबर को एक भाजक के रूप में मानते हैं (1 और 2 को छोड़कर सभी पूर्णांक संख्या के लिए सही ढंग से काम करते हैं)

int number_of_divisors(int n)
{
    int counter,i;
    for(counter=0,i=1;(!(n%i) && (counter++)) || i<=(n/2);i++);
    return ++counter;
}

नोट: उपरोक्त सभी फ़ंक्शन नंबर 1 और 2 को छोड़कर सभी सकारात्मक पूर्णांक संख्या के लिए सही ढंग से काम करते हैं, इसलिए यह सभी संख्याओं के लिए कार्यात्मक है जो 2 से अधिक हैं, लेकिन यदि आपको 1 और 2 को कवर करने की आवश्यकता है, तो आप निम्न कार्यों में से एक का उपयोग कर सकते हैं (थोड़ा और धीमा)

int number_of_divisors(int n)
{
    int counter,i;
    for(counter=0,i=1;(!(n%i) && (counter++)) || i<=(n/2);i++);
    if (n==2 || n==1)
    {
    return counter;
    }
    return ++counter;
}

या

int number_of_divisors(int n)
{
    int counter,i;
for(counter=0,i=1;(!(i==n) && !(n%i) && (counter++)) || i<=(n/2);i++);
    return ++counter;
}

छोटा सुंदर होता है :)


5

एटकिन की छलनी, एराटोस्थनीज की छलनी का एक अनुकूलित संस्करण है जो सभी प्रमुख संख्याओं को दिए गए पूर्णांक तक देता है। आपको अधिक विवरण के लिए इसे Google में सक्षम होना चाहिए।

एक बार आपके पास वह सूची होने के बाद, यह देखने के लिए कि क्या यह सटीक विभाजक है (यानी, शेष शून्य है) प्रत्येक प्राइम द्वारा अपने नंबर को विभाजित करना एक साधारण मामला है।

संख्या (n) के लिए भाजक की गणना करने वाले मूल चरण हैं [यह स्यूडोकोड है जिसे वास्तविक कोड से परिवर्तित किया गया है, इसलिए मुझे आशा है कि मैंने त्रुटियों को पेश नहीं किया है]:

for z in 1..n:
    prime[z] = false
prime[2] = true;
prime[3] = true;

for x in 1..sqrt(n):
    xx = x * x

    for y in 1..sqrt(n):
        yy = y * y

        z = 4*xx+yy
        if (z <= n) and ((z mod 12 == 1) or (z mod 12 == 5)):
            prime[z] = not prime[z]

        z = z-xx
        if (z <= n) and (z mod 12 == 7):
            prime[z] = not prime[z]

        z = z-yy-yy
        if (z <= n) and (x > y) and (z mod 12 == 11):
            prime[z] = not prime[z]

for z in 5..sqrt(n):
    if prime[z]:
        zz = z*z
        x = zz
        while x <= limit:
            prime[x] = false
            x = x + zz

for z in 2,3,5..n:
    if prime[z]:
        if n modulo z == 0 then print z

5

आप यह कोशिश कर सकते हैं। यह थोड़ा हैकिश है, लेकिन यह काफी तेज है।

def factors(n):
    for x in xrange(2,n):
        if n%x == 0:
            return (x,) + factors(n/x)
    return (n,1)

2
जबकि यह फ़ंक्शन उचित समय में n का एक मुख्य कारक अपघटन प्रदान करता है, यह a) इष्टतम नहीं है और b) ओपी के प्रश्न के अनुसार किसी दिए गए नंबर के विभाजकों की संख्या की गणना नहीं करता है
le_m

और इसकी पुनरावृत्ति के कारण बड़ी संख्या के लिए काम नहीं करेगा
whackamadoodle3000

हालांकि यह इष्टतम नहीं है, और कारकों की गिनती के बजाय , यह वास्तव में उन्हें सूचीबद्ध करता है, इस की सादगी और सुंदरता अद्भुत है और यथोचित रूप से तेज है। ^ ^
गौरव सिंघल

5

एक बार आपके पास मुख्य कारक होने के बाद, विभाजकों की संख्या का पता लगाने का एक तरीका है। प्रत्येक व्यक्तिगत कारक पर एक घातांक में से एक को जोड़ें और फिर घातांक को एक साथ गुणा करें।

उदाहरण के लिए: 36 प्रधान कारक: 2 ^ 2 * 3 ^ 2 भाजक: 1, 2, 3, 4, 6, 9, 12, 18, 36 भाजक की संख्या: 9

प्रत्येक घातांक में एक 2 ^ 3 * 3 ^ 3 गुणा करें: 3 * 3 = 9


3

इससे पहले कि आप एक समाधान करने के लिए विचार करें कि छलनी दृष्टिकोण ठेठ मामले में एक अच्छा जवाब नहीं हो सकता है।

थोड़ी देर पहले एक प्रमुख सवाल था और मैंने एक समय परीक्षण किया था - 32-बिट पूर्णांक के लिए कम से कम यह निर्धारित करना कि यह प्रमुख था, जो कि बल की तुलना में धीमा था। दो कारक हैं:

1) जबकि एक मानव को एक विभाजन करने में कुछ समय लगता है, वे कंप्यूटर पर बहुत जल्दी होते हैं - जवाब देखने की लागत के समान।

2) अगर आपके पास प्राइम टेबल नहीं है तो आप एक लूप बना सकते हैं जो पूरी तरह से एल 1 कैश में चलता है। इससे यह तेज हो जाता है।


3

यह एक कुशल उपाय है:

#include <iostream>
int main() {
  int num = 20; 
  int numberOfDivisors = 1;

  for (int i = 2; i <= num; i++)
  {
    int exponent = 0;
    while (num % i == 0) {
        exponent++; 
        num /= i;
    }   
    numberOfDivisors *= (exponent+1);
  }

  std::cout << numberOfDivisors << std::endl;
  return 0;
}

2

भाजक कुछ शानदार करते हैं: वे पूरी तरह से विभाजित होते हैं। आप एक संख्या के लिए divisors की संख्या की जांच करना चाहते हैं, nयह स्पष्ट रूप से पूरे स्पेक्ट्रम को पार करने वाली अनावश्यक, है 1...n। मैंने इसके लिए कोई गहन शोध नहीं किया है लेकिन मैंने त्रिकोणीय संख्याओं पर प्रोजेक्ट यूलर की समस्या 12 को हल कर दिया है । 309504 माइक्रोसेकंड (~ 0.3) के लिए 500 से अधिक दिव्यांग परीक्षण के लिए मेरा समाधान । मैंने समाधान के लिए इस विभाजक कार्य को लिखा।

int divisors (int x) {
    int limit = x;
    int numberOfDivisors = 1;

    for (int i(0); i < limit; ++i) {
        if (x % i == 0) {
            limit = x / i;
            numberOfDivisors++;
        }
    }

    return numberOfDivisors * 2;
}

प्रत्येक एल्गोरिदम के लिए, एक कमजोर बिंदु है। मुझे लगा कि यह प्राइम नंबरों के खिलाफ कमजोर था। लेकिन चूंकि त्रिकोणीय संख्याएं प्रिंट नहीं हैं, इसने अपने उद्देश्य को निर्दोष रूप से पूरा किया। मेरी प्रोफाइलिंग से, मुझे लगता है कि इसने बहुत अच्छा किया।

छुट्टियां आनंददायक हों।


1
आप पहली बार यात्रा पर 0 द्वारा विभाजन यहाँ होगा
barfoon

दुर्भाग्य से नहीं। ++ i, i ++ से अलग है (जिसके परिणामस्वरूप विभाजित-शून्य त्रुटि होगी)
iGbanam

मैंने PHP में आपके फ़ंक्शन को लिखा और इसे चलाया - यहाँ मुझे क्या मिला - i.minus.com/iKzuSXesAkpbp.png
बारफून

कुछ अजीब कारण के लिए, यह मेरे लिए निर्दोष काम किया। ओह अच्छा, मेरी बुर। numberOfDivisors1 पर प्रारंभ और पुनरावृत्त; यह शून्य त्रुटि से विभाजन से छुटकारा पाना चाहिए
iGbanam

1
आपका एल्गोरिथ्म सही वर्गों के लिए काम नहीं करता है। उदाहरण के लिए, यह इनपुट x = 4 के लिए 4 लौटाता है, क्योंकि यह 2 दो बार गिन रहा है ... 1, 2, 2, 4. उत्तर 3: 1,2,4 होना चाहिए
माइकल

1

आप यहाँ वर्णित एटकिन की छलनी चाहते हैं: http://en.wikipedia.org/wiki/Sieve_of_Atkin


1
यह आपको दिए गए नंबरों के नीचे दिए गए प्राइमर पाने वाला है - लेकिन इस बात की कोई गारंटी नहीं है कि वे प्राइमर डिवाइडर बनने वाले हैं? (जब तक मैं कुछ याद नहीं कर रहा हूं)
एंड्रयू एडगेकोम्बे

यह यहाँ से एक त्वरित छलांग है, सभी primes को खोजने के लिए <sqrt (N) जो समान रूप से N को विभाजित करता है
SquareCog

1
यह एक त्वरित छलांग हो सकती है, लेकिन सभी अपराधों का परीक्षण करना <sqrt (N) अभी भी एक खराब फैक्टरिंग तकनीक है, चाहे वह कितनी भी कुशलता से उन्हें खोज ले। इसमें सुधार करने के कई तरीके हैं।
user11318

प्रिम्स का परीक्षण O (N) है, यह उन प्राइम को ढूंढ रहा है जो कठिन हिस्सा है। लेकिन एराटोस्थनीज की अडॉप्टिमाइज्ड छलनी के साथ, आप अभी भी एक सेकंड के तहत कुछ मिलियन के तहत सभी प्राइम्स पा सकते हैं। यह किसी भी 64b संख्या को कवर करता है, और मुझे यकीन है कि हम यहां क्रिप्टो स्तर के सामान को फैक्टर करने के बारे में बात नहीं कर रहे हैं
मैथ्यू शारले

1

अभाज्य संख्या विधि यहाँ बहुत स्पष्ट है। P [] वर्ग = sqrt (n) से कम या बराबर अभाज्य संख्या की एक सूची है;

for (int i = 0 ; i < size && P[i]<=sq ; i++){
          nd = 1;
          while(n%P[i]==0){
               n/=P[i];
               nd++;
               }
          count*=nd;
          if (n==1)break;
          }
      if (n!=1)count*=2;//the confusing line :D :P .

     i will lift the understanding for the reader  .
     i now look forward to a method more optimized  .

1

संख्या सिद्धांत पाठ्यपुस्तकें डिवाइज़र-काउंटिंग फ़ंक्शन ताऊ कहती हैं। पहला दिलचस्प तथ्य यह है कि यह गुणक है, अर्थात। τ (एबी) = τ (ए) b (बी), जब ए और बी का कोई सामान्य कारक नहीं है। (प्रमाण: a और b के विभाजकों की प्रत्येक जोड़ी ab का एक अलग विभाजक देती है)।

अब ध्यान दें कि पीए प्राइम के लिए, τ (पी ** के) = के + 1 (पी की शक्तियां)। इस प्रकार आप आसानी से इसके कारक से τ (n) की गणना कर सकते हैं।

हालांकि बड़ी संख्या में फैक्टरिंग धीमी हो सकती है (आरएसए क्रायोप्रोटी की सुरक्षा दो बड़े अपराधों के कारक पर निर्भर होने के कारण निर्भर करती है)। यह इस अनुकूलित एल्गोरिदम का सुझाव देता है

  1. परीक्षण करें यदि संख्या प्रधान है (तेज़)
  2. यदि हां, तो 2 वापस करें
  3. अन्यथा, संख्या को गुणन करें (यदि कई बड़े अभाज्य गुणक हैं तो धीमा)
  4. गुणनखंड से n (n) की गणना करें

1

किसी दिए गए नंबर के विभाजकों की संख्या ज्ञात करने के लिए निम्नलिखित C प्रोग्राम है।

उपरोक्त एल्गोरिथ्म की जटिलता हे (sqrt (n))।

यह एल्गोरिथ्म सही ढंग से उस संख्या के लिए काम करेगा जो पूर्ण वर्ग के साथ-साथ उन संख्याओं के लिए भी है जो पूर्ण वर्ग नहीं हैं।

नोट करें कि लूप का ऊपरी भाग एल्गोरिथ्म को सबसे कुशल बनाने के लिए संख्या के वर्ग-मूल पर सेट है।

ध्यान दें कि एक अलग चर में ऊपरी भाग को संग्रहीत करने से भी समय की बचत होती है, आपको लूप के लिए स्थिति खंड में sqrt फ़ंक्शन को कॉल नहीं करना चाहिए, यह आपके कम्प्यूटेशनल समय को भी बचाता है।

#include<stdio.h>
#include<math.h>
int main()
{
    int i,n,limit,numberOfDivisors=1;
    printf("Enter the number : ");
    scanf("%d",&n);
    limit=(int)sqrt((double)n);
    for(i=2;i<=limit;i++)
        if(n%i==0)
        {
            if(i!=n/i)
                numberOfDivisors+=2;
            else
                numberOfDivisors++;
        }
    printf("%d\n",numberOfDivisors);
    return 0;
}

लूप के लिए उपरोक्त के बजाय आप निम्न लूप का भी उपयोग कर सकते हैं जो और भी अधिक कुशल है क्योंकि यह संख्या के वर्ग-मूल को खोजने की आवश्यकता को हटा देता है।

for(i=2;i*i<=n;i++)
{
    ...
}

1

यहाँ एक फ़ंक्शन है जो मैंने लिखा था। यह सबसे खराब समय जटिलता O (sqrt (n)) है, दूसरी ओर सबसे अच्छा समय O (log (n)) है। यह आपको सभी प्राइम डिविजर्स को इसके होने की संख्या के साथ देता है।

public static List<Integer> divisors(n) {   
    ArrayList<Integer> aList = new ArrayList();
    int top_count = (int) Math.round(Math.sqrt(n));
    int new_n = n;

    for (int i = 2; i <= top_count; i++) {
        if (new_n == (new_n / i) * i) {
            aList.add(i);
            new_n = new_n / i;
            top_count = (int) Math.round(Math.sqrt(new_n));
            i = 1;
        }
    }
    aList.add(new_n);
    return aList;
}

मुझे नहीं पता कि यह फ़ंक्शन क्या गणना करता है, लेकिन यह निश्चित रूप से n के भाजक की सूची नहीं है।
le_m

1

यह संख्या परिकलन की गणना का सबसे बुनियादी तरीका है:

class PrintDivisors
{
    public static void main(String args[])
    {

    System.out.println("Enter the number");

    // Create Scanner object for taking input
    Scanner s=new Scanner(System.in);

    // Read an int
    int n=s.nextInt();

        // Loop from 1 to 'n'
        for(int i=1;i<=n;i++)
        {

            // If remainder is 0 when 'n' is divided by 'i',
            if(n%i==0)
            {
            System.out.print(i+", ");
            }
        }

    // Print [not necessary]    
    System.out.print("are divisors of "+n);

    }
}

1

@Kendall

मैंने आपके कोड का परीक्षण किया और कुछ सुधार किए, अब यह और भी तेज है। मैंने @ هومن جاویدرور कोड के साथ परीक्षण भी किया, यह उनके कोड से भी तेज है।

long long int FindDivisors(long long int n) {
  long long int count = 0;
  long long int i, m = (long long int)sqrt(n);
  for(i = 1;i <= m;i++) {
    if(n % i == 0)
      count += 2;
  }
  if(n / m == m && n % m == 0)
    count--;
  return count;
}

0

क्या यह केवल संख्या को फैक्टर करने का सवाल नहीं है - संख्या के सभी कारकों को निर्धारित करना? फिर आप यह तय कर सकते हैं कि आपको एक या अधिक कारकों के सभी संयोजनों की आवश्यकता है या नहीं।

तो, एक संभव एल्गोरिथ्म होगा:

factor(N)
    divisor = first_prime
    list_of_factors = { 1 }
    while (N > 1)
        while (N % divisor == 0)
            add divisor to list_of_factors
            N /= divisor
        divisor = next_prime
    return list_of_factors

फिर बाकी उत्तर निर्धारित करने के लिए कारकों को संयोजित करना आपके ऊपर है।


0

यह कुछ ऐसा है जो मैं जस्टिन के उत्तर पर आधारित था। इसके लिए कुछ अनुकूलन की आवश्यकता हो सकती है।

n=int(input())

a=[]
b=[]

def sieve(n):
    np = n + 1
    s = list(range(np)) 
    s[1] = 0
    sqrtn = int(n**0.5)
    for i in range(2, sqrtn + 1): 
        if s[i]:
            s[i*i: np: i] = [0] * len(range(i*i, np, i))
    return filter(None, s)

k=list(sieve(n))

for i in range(len(k)):
        if n%k[i]==0:
                a.append(k[i])

a.sort()

for i in range(len(a)):
        j=1
        while n%(a[i]**j)==0: 
                j=j+1
        b.append(j-1)

nod=1

for i in range(len(b)):
        nod=nod*(b[i]+1)

print('no.of divisors of {} = {}'.format(n,nod))

0

मुझे लगता है कि यह वही है जो आप ढूंढ रहे हैं। मैं वही करता हूं जो आपने मांगा था। इसे नोटपैड में कॉपी और पेस्ट करें। * .bat.Run.Enter Number.ult के रूप में 2 से प्रक्रिया करें और विभाजकों की संख्या को मानें। मैंने इसे उद्देश्य पर बनाया ताकि यह तेजी से निर्धारित होता है:

Pls ध्यान दें कि 999999999 पर एक CMD वेरिएबल कैंट समर्थन मूल्य

@echo off

modecon:cols=100 lines=100

:start
title Enter the Number to Determine 
cls
echo Determine a number as a product of 2 numbers
echo.
echo Ex1 : C = A * B
echo Ex2 : 8 = 4 * 2
echo.
echo Max Number length is 9
echo.
echo If there is only 1 proces done  it
echo means the number is a prime number
echo.
echo Prime numbers take time to determine
echo Number not prime are determined fast
echo.

set /p number=Enter Number : 
if %number% GTR 999999999 goto start

echo.
set proces=0
set mindet=0
set procent=0
set B=%Number%

:Determining

set /a mindet=%mindet%+1

if %mindet% GTR %B% goto Results

set /a solution=%number% %%% %mindet%

if %solution% NEQ 0 goto Determining
if %solution% EQU 0 set /a proces=%proces%+1

set /a B=%number% / %mindet%

set /a procent=%mindet%*100/%B%

if %procent% EQU 100 set procent=%procent:~0,3%
if %procent% LSS 100 set procent=%procent:~0,2%
if %procent% LSS 10 set procent=%procent:~0,1%

title Progress : %procent% %%%



if %solution% EQU 0 echo %proces%. %mindet% * %B% = %number%
goto Determining

:Results

title %proces% Results Found
echo.
@pause
goto start

882161280 - 1282
डिविजर्स

0

मुझे लगता है कि यह एक के साथ-साथ सटीक भी होगा

script.pyton

>>>factors=[ x for x in range (1,n+1) if n%x==0] print len(factors)


0

इन पंक्तियों के साथ कुछ आज़माएँ:

int divisors(int myNum) {
    int limit = myNum;
    int divisorCount = 0;
    if (x == 1) 
        return 1;
    for (int i = 1; i < limit; ++i) {
        if (myNum % i == 0) {
            limit = myNum / i;
            if (limit != i)
                divisorCount++;
            divisorCount++;
        }
    }
    return divisorCount;
}

-1

मैं सबसे कुशल विधि नहीं जानता, लेकिन मैं निम्नलिखित काम करूंगा:

  • संख्या के वर्गमूल से कम या बराबर सभी व्यक्तिगत खोजने के लिए primes की तालिका बनाएं (व्यक्तिगत रूप से, मैं Atkin की चलनी का उपयोग करूंगा)
  • संख्या की वर्गमूल से कम या बराबर सभी primes की गणना करें और दो से गुणा करें। यदि संख्या का वर्गमूल एक पूर्णांक है, तो गणना चर से एक घटाएं।

काम करना चाहिए / ओ /

यदि आपको आवश्यकता है, तो मैं कल सी में कुछ प्रदर्शित करने के लिए कोड कर सकता हूं।


2
मैं उलझन में हूं। किसी संख्या के वर्गमूल से कम के सभी अपराधों को गिनना आपको यह भाजक नहीं देगा ... किसी संख्या के वर्गमूल से कम प्रत्येक अभाज्य संख्या के लिए भाजक नहीं होगा।
गैरेट बर्ग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.