Factorials modulo a prime की गणना करने का सबसे कुशल तरीका क्या है?


20

क्या आप किसी भी एल्गोरिथ्म को जानते हैं जो मापांक के बाद कुशलता से गणना करता है?

उदाहरण के लिए, मैं कार्यक्रम करना चाहता हूं:

for(i=0; i<5; i++)
  sum += factorial(p-i) % p;

लेकिन, pसीधे फैक्टरियल लागू करने के लिए एक बड़ी संख्या (प्राइम) है ।(p108)

पायथन में, यह कार्य वास्तव में आसान है, लेकिन मैं वास्तव में यह जानना चाहता हूं कि अनुकूलन कैसे करें।


6
लगता है कि समस्या आपको विल्सन के प्रमेय का उपयोग करने के लिए चाहती है। प्राइम p , । तो किसी भी प्रोग्रामिंग भाषा का उपयोग किए बिना: उत्तर । शायद आप अपनी समस्या को सामान्य करना चाहेंगे? 100(p1)!=1modp100
आर्यभट्ट

5
क्या आप समस्या को अधिक स्पष्ट रूप से बता सकते हैं? क्या आप गणना करना चाहते हैं (X!) (mod (X+1)), या अधिक सामान्य (X!) (mod Y)? और मुझे लगता है कि factorial(100!)वास्तव में इसका मतलब यह नहीं है कि आप दो बार फैक्टरियल फंक्शन लागू करना चाहते हैं।
कीथ थॉम्पसन

1
यहां तक ​​कि अगर आपके पास विल्सन का प्रमेय नहीं है, तो आपके पास वह , जो कम से कम अतिप्रवाह मुद्दों से बचने में मदद करेगा। (mn)modp=(mmodp)(nmodp)
डेव क्लार्क

8
ध्यान दें कि विल्सन के प्रमेय केवल तभी लागू होते हैं जब p प्रमुख होता है। आपका प्रश्न यह नहीं बताता है कि p अभाज्य है, इसलिए आपने जो लिखा है वह सही नहीं है।
डेव क्लार्क

जवाबों:


11

(यह उत्तर प्रारंभ में प्रश्नकर्ता के अंदर प्रश्नकर्ता जोनाप्रिएटो द्वारा पोस्ट किया गया था ।)

मुझे विल्सन की प्रमेय याद है , और मैंने छोटी चीजों पर ध्यान दिया:

उपरोक्त कार्यक्रम में, यह बेहतर है अगर मैं लिखूँ:

(p1)!1(modp)(p2)!(p1)!(p1)11(modp)(p3)!(p2)!(p2)1(p2)1(modp)(p4)!(p3)!(p3)1(p2)1(p3)1(modp) (p5)!(p4)!(p4)1(p2)1(p3)1(p4)1(modp)

और आप पा सकते हैं क्योंकि , इसलिए विस्तारित यूक्लिडियन एल्गोरिथ्म के साथ आप का मान पा सकते हैं , जो है उलटा मापांक। gcd ( p , p - i ) = 1 ( p - i ) - 1(pi)1gcd(p,pi)=1(pi)1

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

(p5)!(p24)1(modp)(p4)!(p+6)1(modp)(p3)!(p2)1(modp)(p2)!1(modp)(p1)!1(modp)
(24)1+(6)1+(2)1
8(24)1(modp)

तो मूल रूप से । साफ! (pk)!(p+(k1)!(1)k)1(modp)
थॉमस अहले

क्षमा करें, लेकिन जब मैं कारक , मुझे मिलता है: 9 ( - 24 ) - 1 = - 3(24)1+61+(2)1
9(24)1=38

1

जो उदाहरण आप पोस्ट कर रहे हैं वह Euler समस्या # 381 से बहुत निकट से संबंधित है। इसलिए मैं एक उत्तर दूंगा जो ईयूलर समस्या को हल नहीं करता है। मैं पोस्ट करूँगा कि कैसे आप factorials modulo a prime की गणना कर सकते हैं।

तो: n की गणना कैसे करें! मोडुलो पी?

त्वरित अवलोकन: यदि n, p, तो n! एक कारक p है, इसलिए परिणाम 0. बहुत जल्दी है। और अगर हम आवश्यकता को अनदेखा करते हैं कि पी को एक प्रधान होना चाहिए तो q को p, और n का सबसे छोटा प्रधान कारक होने दें! modulo p 0 है अगर n। q। यह भी आवश्यक नहीं है कि आपके प्रश्न का उत्तर देने के लिए p एक प्रधान है।

अब आपके उदाहरण में (n - i)! 1 ≤ i ≤ 5 के लिए आया था। आपको पाँच फैक्टरियों की गणना करने की आवश्यकता नहीं है: आप गणना करते हैं (n - 5) !, (n - 4) से गुणा करें (n - 4) जाएँ! (प्राप्त करने के लिए (n - 3) से गुणा करें (n - 3)! आदि। यह काम को लगभग एक कारक से कम कर देता है 5. समस्या का शाब्दिक रूप से समाधान न करें।

सवाल यह है कि एन की गणना कैसे करें! modulo m। स्पष्ट तरीका यह है कि n की गणना करें !, एक संख्या लगभग n n n दशमलव अंकों के साथ, और शेष modulo p की गणना करें। यही मेहनत है। प्रश्न: हम इस परिणाम को जल्दी कैसे प्राप्त कर सकते हैं? स्पष्ट काम न करके।

हम जानते हैं कि ((a * b * c) modulo p = (((a * b) modulo p) * c) modulo p।

N की गणना करने के लिए !, हम सामान्य रूप से x = 1 से शुरू करेंगे, फिर x को 1, 2, 3, ... n से गुणा करेंगे। मोडुलो फॉर्मूला का उपयोग करके, हम n की गणना करते हैं! modulo p की गणना बिना n !, x = 1 से शुरू करके, और फिर i = 1, 2, 3, .. के लिए, n को x के साथ x (x * i) modulo p से प्रतिस्थापित करते हैं।

हमारे पास हमेशा x <p और i <n होता है, इसलिए हमें केवल x * p की गणना करने के लिए पर्याप्त सटीकता की आवश्यकता होती है, न कि गणना करने के लिए बहुत उच्च परिशुद्धता की!। तो n की गणना करने के लिए! modulo p for p we 2 हम निम्नलिखित कदम उठाते हैं:

Step 1: Find the smallest prime factor q of p. If n ≥ q then the result is 0.
Step 2: Let x = 1, then for 1 ≤ i ≤ n replace x with (x * i) modulo p, and x is the result. 

(कुछ उत्तर विल्सन के प्रमेय का उल्लेख करते हैं, जो केवल दिए गए उदाहरण के बहुत ही विशेष मामले में प्रश्न का उत्तर देता है, और Euler समस्या को हल करने के लिए बहुत उपयोगी है # 381, लेकिन सामान्य रूप से उस प्रश्न को हल करने के लिए उपयोगी नहीं है जो पूछा गया था)।


-1

यह मेरे विल्सन के प्रमेय का कार्यान्वयन उपयोग है:

FactMOD फ़ंक्शन एक है जिसे कंप्यूट करने के लिए कहा जाता है (n!)% MOD जब MOD-n n से कम होता है।

क्या कोई अन्य कुशल दृष्टिकोण जानता है जब यह मामला नहीं है (जैसे: n = 1e6 और MOD = 1e9 + 7)?

ll powmod(ll a, ll b){//a^b % MOD
  ll x=1,y=a;
  while(b){
    if(b&1){
      x*=y; if(x>=MOD)x%=MOD;
    }
    y*=y; if(y>=MOD)y%=MOD;
    b>>=1;
  }
  return x;
} 
ll InverseEuler(ll n){//modular inverse of n
  return powmod(n,MOD-2);
}
ll factMOD(ll n){ //n! % MOD efficient when MOD-n<n
   ll res=1,i;
   for(i=1; i<MOD-n; i++){
     res*=i;
     if(res>=MOD)res%=MOD;
   }
   res=InverseEuler(res);   
    if(!(n&1))
      res= -res +MOD;
  }
  return res%MOD;
}

1
कोड वास्तव में विषय पर नहीं है, यहाँ है। एल्गोरिथ्म का वर्णन अधिक उपयोगी है क्योंकि इससे लोगों को यह समझने की आवश्यकता नहीं होती है कि आपने अपने कोड को लिखने के लिए जो भी भाषा तय की है, और क्योंकि वास्तविक कार्यान्वयन अक्सर इस तरह से अनुकूलित होते हैं जिससे उन्हें समझना कठिन हो जाता है। और कृपया अपने प्रश्नों को अपने उत्तर के बजाय अलग-अलग प्रश्न पूछें। स्टैक एक्सचेंज एक प्रश्न और उत्तर साइट है, एक चर्चा बोर्ड नहीं है, और यदि वे उत्तर छिपाए हुए हैं तो प्रश्न खोजना कठिन है। धन्यवाद!
डेविड रिचीर्बी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.