2016-10-11 6 views
5

मैं वर्तमान में ProjectEuler problem को हल करने का प्रयास कर रहा हूं और गति को छोड़कर मुझे सबकुछ नीचे मिल गया है। मैं लगभग निश्चित रूप से निश्चित रूप से निष्पादित करता हूं कि घोंसला वाले लूप के कारण कार्यक्रम धीरे-धीरे निष्पादित होता है। मुझे इस बारे में कुछ सलाह चाहिए कि इसे कैसे गति दें। मैं एक नौसिखिया प्रोग्रामर हूं, इसलिए मैं बहुत अधिक उन्नत तरीकों/विषयों से परिचित नहीं हूं।मैं इस कार्यक्रम को कैसे बढ़ाऊंगा?

public class Problem12 { 

    public static void main(String[] args) { 
     int num; 

     for (int i = 1; i < 15000; i++) { 
      num = i * (i + 1)/2; 
      int counter = 0; 

      for (int x = 1; x <= num; x++) { 
       if (num % x == 0) { 
        counter++; 
       } 
      } 
      System.out.println("[" + i + "] - " + num + " is divisible by " + counter + " numbers."); 
     } 
    } 
} 

संपादित करें: नीचे नई कोड तेजी से तेजी से होता है। लगातार लाइन प्रिंटिंग को हटा दिया गया है और साथ ही इसे और भी तेज करने के लिए हटा दिया गया है।

public class Problem12 { 

    public static void main(String[] args) { 
     int num; 

     outerloop: 
     for (int i = 1; i < 25000; i++) { 
      num = i * (i + 1)/2; 
      int counter = 0; 

      double root = Math.sqrt(num); 
      for (int x = 1; x < root; x++) { 
       if (num % x == 0) { 
        counter += 2; 
        if (counter >= 500) { 
         System.out.println("[" + i + "] - " + num + " is divisible by " + counter + " numbers."); 
         break outerloop; 
        } 
       } 
      } 
     } 
    } 
} 
+1

सी की तरह एक तेजी से भाषा का उपयोग करके देखें, और सब पर इस एल्गोरिथ्म काम करता है, विभाजन के बजाय bitshifts और गुणा उपयोग करने का प्रयास करता है, तो वे जावा –

+0

में उपलब्ध हैं? तो अगर 'i = 3' फिर' num = 6' और फिर 'counter = 4' जो गलत है – afsafzal

+4

@SheheAnsar आप कैसे मान सकते हैं कि सी जावा के लिए तेज़ है, अगर आपको यह जानने के लिए पर्याप्त नहीं है कि क्या बिट्सफिफ्ट समर्थित हैं? – njzk2

उत्तर

5

शुरुआत के लिए, जब divisors को देखते हुए, आप संख्या की जड़ वर्ग से आगे जाने के लिए, की जरूरत कभी नहीं क्योंकि वर्गमूल नीचे प्रत्येक भाजक ऊपर एक बराबर है।

n = a * b => a <= sqrt(n) or b <= sqrt(n) 

तो फिर तुम विभाजन के दूसरी ओर गिनती करने के लिए की जरूरत है:

double root = Math.sqrt(num); 
for (int x = 1; x < root; x++) { 
    if (num % x == 0) { 
     counter += 2; 
    } 
} 

वर्गमूल खास है क्योंकि यह केवल एक बार अगर यह पूर्णांक है मायने रखता है:

if ((double) ((int) root) == root) { 
    counter += 1; 
} 
+0

यह चाल है। हालांकि, मुझे यकीन नहीं है कि कैसे। क्या आप इस बात पर कुछ और बताएंगे कि यह क्यों काम करता है? – jxshu

+1

प्रत्येक divisor एक जोड़ी के रूप में काम करता है, यही कारण है कि हम प्रत्येक दो बार गिनती है। प्रत्येक जोड़ी के लिए, तत्व में से एक वर्ग रूट के नीचे है, दूसरा एक ऊपर है। यह देखना आसान है: यदि दोनों तत्व ऊपर हैं, तो परिणाम भी ऊपर है। यदि दोनों नीचे हैं, तो परिणाम भी नीचे है। उदाहरण: '10 = 2 * 5 = 1 * 10'। 2 और 1 3.16 से नीचे हैं, 5 और 10 ऊपर हैं। – njzk2

+0

althoug, मैं कोई त्रिकोणीय _and_ वर्ग संख्या नहीं होने के बारे में गलत था, अब संपादन – njzk2

0

तुम बस संख्या को कारगर करने की आवश्यकता है। p^a * q^b * r^c में (a+1)*(b+1)*(c+1) divisors है। यहाँ इस विचार का उपयोग कर कुछ बुनियादी कार्यान्वयन है:

static int Divisors(int num) { 
    if (num == 1) { 
     return 1; 
    } 

    int root = (int) Math.sqrt(num); 
    for (int x = 2; x <= root; x++) { 
     if (num % x == 0) { 
      int c = 0; 
      do { 
       ++c; 
       num /= x; 
      } while (num % x == 0); 
      return (c + 1) * Divisors(num); 
     } 
    } 

    return 2; 
} 

public static void test500() { 
    int i = 1, num = 1; 
    while (Divisors(num) <= 500) { 
     num += ++i; 
    } 

    System.out.println("\nFound: [" + i + "] - " + num); 
} 
संबंधित मुद्दे