ঠিক এবং দ্রুত কোনও সম্ভাবনা গণনা করুন


10

[ সম্ভাব্যতাটি হুবহু গণনার জন্য এটি একটি অংশীদার প্রশ্ন ]

এই টাস্কটি সম্ভাব্যতার সঠিক এবং দ্রুত গণনা করার জন্য কোড লেখার বিষয়ে । আউটপুটটি তার সর্বাধিক হ্রাসকৃত আকারে ভগ্নাংশ হিসাবে লিখিত একটি সুনির্দিষ্ট সম্ভাবনা হওয়া উচিত। এটি কখনও কখনও আউটপুট করা উচিত 4/8নয় 1/2

কিছু ধনাত্মক পূর্ণসংখ্যার জন্য n, 1s এবং -1s দৈর্ঘ্যের একরকম এলোমেলো স্ট্রিং বিবেচনা করুন nএবং এটিকে এ কল করুন Aits এখন এটির প্রথম মানটির সাথে সম্মতি দিন । যে A[1] = A[n+1]যদি 1. থেকে ইন্ডেক্স Aএখন দৈর্ঘ্য n+1। এখন দৈর্ঘ্যের দ্বিতীয় এলোমেলো স্ট্রিং বিবেচনা করুন nযার nসম্ভাব্যতা 1 / 4,1 / 2, 1/4 সহ প্রথম মান -1, 0, বা 1 হয় এবং এটিকে বি কল করুন call

এখন ভেতরের পণ্য বিবেচনা A[1,...,n]এবং Bএবং ভিতরের পণ্য A[2,...,n+1]এবং B

উদাহরণস্বরূপ, বিবেচনা করুন n=3। সম্ভাব্য মান Aএবং Bহতে পারে A = [-1,1,1,-1]এবং B=[0,1,-1]। এক্ষেত্রে দুটি অভ্যন্তরীণ পণ্য হ'ল 0এবং 2

আপনার কোডটি অবশ্যই উভয় অভ্যন্তরীণ পণ্য শূন্য হওয়ার সম্ভাবনা আউটপুট করে।

মার্টিন বাটনার দ্বারা উত্পাদিত টেবিলটি অনুলিপি করা হচ্ছে আমাদের নিম্নলিখিত নমুনার ফলাফল রয়েছে।

n   P(n)
1   1/2
2   3/8
3   7/32
4   89/512
5   269/2048
6   903/8192
7   3035/32768
8   169801/2097152

ভাষা ও গ্রন্থাগার

আপনি যে কোনও অবাধে উপলভ্য ভাষা এবং লাইব্রেরি ব্যবহার করতে পারেন। আমি অবশ্যই আপনার কোডটি চালাতে সক্ষম হব তাই দয়া করে আপনার কোড লিনাক্সে কীভাবে চালানো / সংকলন করা যায় তার সম্পূর্ণ ব্যাখ্যা অন্তর্ভুক্ত করুন যদি সম্ভব হয় তবে।

কাজটি

আপনার কোডটি অবশ্যই শুরু করা উচিত n=1এবং পৃথক লাইনে প্রতিটি ক্রমবর্ধমান এনের জন্য সঠিক আউটপুট দিতে হবে । এটি 10 ​​সেকেন্ড পরে থামানো উচিত।

হিসাব

nআমার কম্পিউটারে চালানোর সময় আপনার কোডটি 10 ​​সেকেন্ড পরে থামার আগে স্কোরটি সর্বাধিক পৌঁছে যায়। যদি কোনও টাই থাকে, তবে বিজয়ী সর্বোচ্চতম স্কোরটি পাওয়ার জন্য এক হন।

এন্ট্রি সারণী

  • n = 64মধ্যে পাইথন । সংস্করণ 1 মিচ শোয়ার্জ দ্বারা রচিত
  • n = 106মধ্যে পাইথন । সংস্করণ 11 জুন 2015 মিচ শোয়ার্জ দ্বারা
  • n = 151মধ্যে সি ++ । পোর্ট অফ মিচ শোয়ার্জ-এর উত্তর দ্বারা কিরবিফ্যান64সোস
  • n = 165মধ্যে পাইথন । সংস্করণ 11 ই জুন 2015 মিচ শোয়ার্টজের সাথে "ছাঁটাই" সংস্করণ N_MAX = 165
  • n = 945মধ্যে পাইথন Min_25 দ্বারা একটি সঠিক সূত্র ব্যবহার করে। অ্যামেজিং!
  • n = 1228মধ্যে পাইথন মিচ শোয়ার্জ দ্বারা অন্য সঠিক সূত্র (Min_25 পূর্ববর্তী উত্তর উপর ভিত্তি করে) ব্যবহার করে।
  • n = 2761মধ্যে পাইথন মিচ শোয়ার্জ দ্বারা একই সঠিক সূত্রের একটি দ্রুত বাস্তবায়ন ব্যবহার করে।
  • n = 3250মধ্যে পাইথন ব্যবহার Pypy মিচ শোয়ার্জ একই বাস্তবায়ন ব্যবহার করে। এই স্কোরটির pypy MitchSchwartz-faster.py |tailজন্য কনসোল স্ক্রোলিং ওভারহেড এড়ানো দরকার ।

আমি অবাক হয়েছি যদি একটি ন্যালি সমাধান বুস্ট সি ++ এর চেয়ে দ্রুত চলে?
qwr

@ কিউইউআর আমি মনে করি পাইথন পরিবারের মধ্যে থাকায় অদ্ভুত, নাম্বা এবং সিথন সবই আকর্ষণীয় হবে।

2
আমি এই দ্রুততম কোড সমস্যাগুলি আরও দেখতে চাই
qwr

@ কিউআর এটি আমার প্রিয় ধরণের প্রশ্ন ... ধন্যবাদ! চ্যালেঞ্জটি হ'ল এমন একটি সন্ধান করুন যা আপনি খুঁজে পেতে পারেন এমন নীচের স্তরের ভাষায় ঠিক একই অ্যালগরিদমকে কোডিংয়ের সাথে জড়িত না।

আপনি কি কনসোল বা কোনও ফাইলে ফলাফল লিখছেন? পাইপি ব্যবহার করা এবং একটি ফাইল লেখা আমার কাছে দ্রুত বলে মনে হয় seems কনসোলটি প্রক্রিয়াটি যথেষ্ট গতিবেগ করে।
gnibbler

উত্তর:


24

পাইথন

একটি বদ্ধ ফর্মুলা p(n)হয়

এখানে চিত্র বর্ণনা লিখুন

একটি সূচকীয় উৎপাদিত ফাংশন p(n)হয়

এখানে চিত্র বর্ণনা লিখুন

I_0(x)প্রথম ধরণের পরিবর্তিত বেসেল ফাংশনটি কোথায় ।

2015-06-11 এ সম্পাদনা করুন:
- পাইথন কোডটি আপডেট করেছে।

2015-06-13 এ সম্পাদনা করুন:
- উপরের সূত্রটির একটি প্রমাণ যুক্ত করা হয়েছে।
- স্থির time_limit
- একটি PARI / GP কোড যুক্ত করেছে।

পাইথন

def solve():
  # straightforward implementation

  from time import time
  from itertools import count

  def binom(n, r):
    return facts[n] // (facts[r] * facts[n - r])

  def p(N):
    ans = 0
    for i in range(1 + N // 2):
      t = binom(2 * (N - 2 * i), N - 2 * i)
      t *= binom(N, 2 * i)
      t *= binom(4 * i, 2 * i)
      ans += t
    e = (ans & -ans).bit_length() - 1
    numer = ans >> e
    denom = 1 << (3 * N - 1 - e)
    return numer, denom

  facts = [1]
  time_limit = 10.0 + time()

  for i in count(1):
    facts.append(facts[-1] * (2 * i - 1))
    facts.append(facts[-1] * (2 * i))

    n, d = p(i)

    if time() > time_limit:
      break

    print("%d %d/%d" % (i, n, d))

solve()

Pari / জিপি

p(n) = polcoeff( (exp(x/2) + 1) * besseli(0, x/4) ^ 2, n) * n!;

প্রুফ:
এই সমস্যাটি দ্বি-মাত্রিক (সীমাবদ্ধ) এলোমেলো হাঁটার সমস্যার মতো।

তাহলে A[i] = A[i+1], আমরা থেকে স্থানান্তর করতে পারেন (x, y)থেকে (x+1, y+1)[1 পথ], (x, y)[2 উপায়ে] বা (x-1, y-1)[1 পথ]।

তাহলে A[i] != A[i+1], আমরা থেকে স্থানান্তর করতে পারেন (x, y)থেকে (x-1, y+1)[1 পথ], (x, y)[2 উপায়ে] বা (x+1, y-1)[1 পথ]।

যাক a(n, m) = [x^m]((x+1)^n + (x-1)^n), b(n) = [x^n](1+x)^{2n}এবং c(n)উপায় থেকে সরাতে সংখ্যা হতে (0, 0)করার (0, 0)সঙ্গে nধাপ।

তারপর, c(n) = \sum_{i=0}^n a(n, i) * b(i) * b(n-i).

যেহেতু p(n) = c(n) / 8^n, আমরা উপরের ক্লোজড-ফর্মুলাটি পেতে পারি।


1
এই .. ভাল .. আশ্চর্যজনক! পৃথিবীতে আপনি সঠিক সূত্রটি কীভাবে গণনা করলেন?

1
কি দারুন! বন্ধ ফর্ম সর্বদা ঝরঝরে!
Qwr

1
@ ল্যাম্বিক: আমি একটি (রুক্ষ) প্রমাণ যুক্ত করেছি।
Min_25

1
@ কিউআর: ধন্যবাদ আমিও তাই মনে করি !
Min_25

1
@ এমবম্ব007: হ্যাঁ তবে এটি একটি কম্পিউটিং টাস্কের পরিবর্তে একটি বাস্তবায়ন কাজ। সুতরাং, আমি এটি সি ++ এ কোড করব না।
Min_25

9

পাইথন

দ্রষ্টব্য: একটি বদ্ধ-ফর্ম সমাধান সন্ধানের জন্য Min_25 এর জন্য অভিনন্দন!

আকর্ষণীয় সমস্যার জন্য ধন্যবাদ! এটি ডিপি ব্যবহার করে সমাধান করা যেতে পারে, যদিও আমি বর্তমানে উচ্চতর স্কোর পাওয়ার জন্য গতির জন্য অনুকূলিত করতে খুব উত্সাহিত বোধ করছি না। এটা গল্ফ জন্য ভাল হতে পারে।

N=39পাইথন ২.7.৫ চলমান এই পুরানো ল্যাপটপে 10 সেকেন্ডের মধ্যে কোড পৌঁছেছে ।

from time import*
from fractions import*
from collections import*

X={(1,0,0,0):1,(-1,0,0,0):1}

T=time()
N=0

while 1:
    Y=defaultdict(lambda:0)
    n=d=0
    for a,b,s,t in X:
        c=X[(a,b,s,t)]
        for A in ( (1,-1) if N else [a] ):
            for B in 1,0,0,-1:
                n+=c*(s+A*B==0==t+A*b+a*B)
                d+=c
                Y[(a,B,s+A*B,t+A*b)]+=c
    if time()>T+10: break
    N+=1
    print N,Fraction(n,d)
    X=Y

Tuple জন্য (a,b,s,t): aপ্রথম উপাদান A, bশেষ উপাদান B, sঅভ্যন্তরীণ পণ্য A[:-1]এবং B, এবং tঅভ্যন্তরীণ পণ্য A[1:-1]এবং B[:-1], পাইথন ফালি স্বরলিপি ব্যবহার করে। আমার কোড অ্যারে Aবা অন্য Bকোথাও সংরক্ষণ করে না , তাই আমি যুক্ত অক্ষরগুলি যথাক্রমে যুক্ত করার জন্য Aএবং পরবর্তী উপাদানগুলিকে উল্লেখ করার জন্য ব্যবহার করি B। এই পরিবর্তনশীল নামকরণ পছন্দটি ব্যাখ্যাটিকে কিছুটা বিশ্রী করে তোলে, তবে A*b+a*Bকোডটি নিজেরাই সুন্দর দেখাবে। মনে রাখবেন যে উপাদানটি যুক্ত হচ্ছে তা Aহ'ল পেনাল্টিমেট এক, কারণ সর্বশেষ উপাদানটি সর্বদা প্রথমটির মতো থাকে। আমি মার্টিন বাটনার 0দু'বার অন্তর্ভুক্ত করার কৌশল ব্যবহার করেছিBপ্রার্থীদের যথাযথ সম্ভাব্যতা বন্টন পেতে। অভিধান X(যার জন্য নামকরণ করা Yহয়েছে N+1) টিপলের মান অনুসারে সমস্ত সম্ভাব্য অ্যারেগুলির গণনা ট্র্যাক করে। সংখ্যক এবং ডিনোমিনেটরের জন্য ভেরিয়েবলগুলি nএবং dস্ট্যান্ড, যে কারণে আমি nসমস্যার বিবৃতিটির নামটির নামকরণ করেছি N

যুক্তির মূল অংশ যে আপনার কাছ থেকে আপডেট করতে পারেন হয় Nকরতে N+1tuple মাত্র মান ব্যবহার করে। প্রশ্নে উল্লিখিত দুটি অভ্যন্তরীণ পণ্য s+A*Bএবং দ্বারা দেওয়া হয়েছে t+A*b+a*B। আপনি যদি সংজ্ঞাগুলি খানিকটা পরীক্ষা করেন তবে এটি স্পষ্ট; লক্ষ্য করুন যে, [A,a]এবং [b,B]বিন্যাসের গত দুই উপাদান Aএবং Bযথাক্রমে।

নোট করুন sএবং tঅনুসারে ছোট এবং আবদ্ধ N, এবং দ্রুত ভাষায় দ্রুত প্রয়োগের জন্য আমরা অ্যারেগুলির পক্ষে অভিধানগুলি এড়াতে পারি।

শুধুমাত্র সাইন ইন মানগুলি পৃথক করে বিবেচনা করে প্রতিসম ব্যবহারের সুযোগ নেওয়া সম্ভব হতে পারে; আমি এটি তাকান না।

মন্তব্য 1 : অভিধানের আকারটি চতুর্ভুজ আকারে বৃদ্ধি পায় N, যেখানে আকারের অর্থ কী-মূল জোড়াগুলির সংখ্যা।

মন্তব্য 2 : যদি আমরা একটি উপরের আবদ্ধ সেট করে রাখি N, তবে আমরা এর জন্য N_MAX - N <= |s|একই ধরণের টুপলগুলি ছাঁটাই করতে পারি t। এটি একটি শোষণকারী রাষ্ট্রকে নির্দিষ্ট করে, বা ছাঁটাই করা রাষ্ট্রগুলির গণনা (যা প্রতিটি পুনরাবৃত্তিতে 8 দ্বারা গুণিত করা প্রয়োজন) সহ পরিপূর্ণরূপে একটি পরিবর্তনশীল দ্বারা সম্পন্ন করা যেতে পারে।

আপডেট : এই সংস্করণটি দ্রুত:

from time import*
from fractions import*
from collections import*

N_MAX=115

def main():
    T=time()

    N=1
    Y={(1,0,0,0):1,(1,1,1,0):1}
    n=1
    thresh=N_MAX

    while time() <= T+10:
        print('%d %s'%(N,Fraction(n,8**N/4)))

        N+=1
        X=Y
        Y=defaultdict(lambda:0)
        n=0

        if thresh<2:
            print('reached MAX_N with %.2f seconds remaining'%(T+10-time()))
            return

        for a,b,s,t in X:
            if not abs(s)<thresh>=abs(t):
                continue

            c=X[(a,b,s,t)]

            # 1,1

            if not s+1 and not t+b+a: n+=c
            Y[(a,1,s+1,t+b)]+=c

            # -1,1

            if not s-1 and not t-b+a: n+=c
            Y[(a,1,s-1,t-b)]+=c

            # 1,-1

            if not s-1 and not t+b-a: n+=c
            Y[(a,-1,s-1,t+b)]+=c

            # -1,-1

            if not s+1 and not t-b-a: n+=c
            Y[(a,-1,s+1,t-b)]+=c

            # 1,0

            c+=c

            if not s and not t+b: n+=c
            Y[(a,0,s,t+b)]+=c

            # -1,0

            if not s and not t-b: n+=c
            Y[(a,0,s,t-b)]+=c

        thresh-=1

main()

অনুকূলিতকরণ কার্যকর করা হয়েছে:

  • সবকিছুতে রাখুন main()- স্থানীয় ভেরিয়েবল অ্যাক্সেস গ্লোবালের চেয়ে দ্রুত
  • N=1চেক এড়ানোর জন্য স্পষ্টভাবে হ্যান্ডেল করুন (1,-1) if N else [a](যা Aশূন্য তালিকা থেকে শুরু করার জন্য উপাদানগুলি যুক্ত করার সময় টিউপলে প্রথম উপাদানটি সামঞ্জস্যপূর্ণ হয় তা প্রয়োগ করে )
  • অভ্যন্তরীণ লুপগুলি তালিকাভুক্ত করুন, যা গুণকেও দূর করে
  • দিগুন করে ফেলবো cএকটি যোগ করার জন্য 0করতে Bদুইবার পরিবর্তে ঐ অপারেশন করছেন
  • ডিনোমিনেটর সর্বদা 8^Nতাই আমাদের এটির খবর রাখার দরকার নেই
  • এখন একাউন্টে প্রতিসাম্য গ্রহণ: আমরা প্রথম উপাদান ঠিক করতে পারবো Aযেমন 1দ্বারা হর ভাগ 2, বৈধ জোড়া যেহেতু (A,B)সঙ্গে A[1]=1এবং যাদের A[1]=-1অস্বীকার দ্বারা একের সাথে এক চিঠিপত্রের মধ্যে রেখে দেওয়া যেতে পারে A। একইভাবে, আমরা প্রথম উপাদানটি Bঅ-নেতিবাচক হিসাবে ঠিক করতে পারি ।
  • এখন ছাঁটাই সঙ্গে। N_MAXএটি আপনার মেশিনে কী স্কোর পেতে পারে তা দেখার জন্য আপনাকে বেড়াতে হবে। N_MAXবাইনারি অনুসন্ধানের দ্বারা উপযুক্তভাবে স্বয়ংক্রিয়ভাবে সন্ধান করার জন্য এটি আবারও লেখা যেতে পারে , তবে অযৌক্তিক বলে মনে হচ্ছে? দ্রষ্টব্য: আশপাশে না পৌঁছানো পর্যন্ত আমাদের ছাঁটাইয়ের অবস্থাটি পরীক্ষা করার দরকার নেই N_MAX / 2, তাই আমরা দুটি পর্যায়ে পুনরাবৃত্তি করে কিছুটা দ্রুতগতি পেতে পারি, তবে আমি সিদ্ধান্ত নিয়েছি সরলতা এবং কোড পরিষ্কারের জন্য নয়।

1
এটি সত্যিই দুর্দান্ত উত্তর! আপনি আপনার গতি বাড়িয়ে কী করেছেন তা ব্যাখ্যা করতে পারেন?

@ ল্যাম্বিক আপনাকে ধন্যবাদ :) একটি ব্যাখ্যা যুক্ত করেছে, এবং আরও একটি ছোট্ট অপ্টিমাইজেশান তৈরি করেছে এবং এটিকে পাইথন 3 সম্মতিযুক্ত করেছে।
মিচ শোয়ার্টজ

আমার কম্পিউটারে, আমি N=57প্রথম সংস্করণ এবং N=75দ্বিতীয়টির জন্য পেয়েছি ।
kirbyfan64sos

আপনার উত্তরগুলি দুর্দান্ত হয়েছে। এটি ঠিক যে মিনিট 5 এর উত্তরটি আরও বেশি ছিল :)

5

পাইথন

Min_25 এর এলোমেলো পদক্ষেপের ধারণাটি ব্যবহার করে, আমি একটি ভিন্ন সূত্রে পৌঁছাতে সক্ষম হয়েছি:

পি (এন) = \ শুরু {কেস} rac frac {\ যোগ _ {i = 0} ^ {f lfloor n / 2 \ rfloor \ om binom {2i} {i} 2 2 \ বিনম {n} 2i} 4 ^ {n-2i}} {8 ^ n} & n \ পাঠ্য {বিজোড়} \ \ frac {\ বিনম {n} / n / 2} ^ 2 + \ যোগ _ {i = 0} ^ {f lfloor n / 2 \ rfloor \ \ binom {2i} {i} ^ 2 \ binom {n} {2i} 4 ^-n-2i}} {8 ^ n} & n \ পাঠ্য এমনকি এমনকি} \ \ শেষ {কেস}

এখানে Min_25 এর উপর ভিত্তি করে পাইথন বাস্তবায়ন রয়েছে:

from time import*
from itertools import*

def main():
    def binom(n, k):
        return facts[n]/(facts[k]*facts[n-k])

    def p(n):
        numer=0
        for i in range(n/2+1):
            t=binom(2*i,i)
            t*=t
            t*=binom(n,2*i)
            t<<=2*(n-2*i)
            numer+=t
        if not n&1:
            numer+=t
        e=(numer&-numer).bit_length()-1
        numer>>=e
        denom=1<<(3*n-e)
        return numer, denom

    facts=[1]
    time_limit=time()+10

    for i in count(1):
        facts.append(facts[-1]*i)

        n,d=p(i)

        if time()>time_limit:
            break

        print("%d %d/%d"%(i,n,d))

main()

ব্যাখ্যা / প্রমাণ:

প্রথমে আমরা সম্পর্কিত গণনা সমস্যাটি সমাধান করি, যেখানে আমরা অনুমতি দিই A[n+1] = -A[1]; এটি হ'ল, অতিরিক্ত উপাদান সম্মিলিতভাবে প্রথম উপাদান Aহতে পারে 1বা -1নির্বিশেষে। সুতরাং আমাদের কতবার A[i] = A[i+1]ঘটে তার উপর নজর রাখার দরকার নেই । আমাদের নিম্নলিখিত র্যান্ডম ওয়াক আছে:

থেকে (x,y)আমরা (x+1,y+1)[1 টি]], (x+1,y-1)[1 উপায়], (x-1,y+1)[1 উপায়], (x-1,y-1)[1 উপায়], (x,y)[4 উপায়] এ যেতে পারি

যেখানে xএবং yদুই ডট পণ্যের জন্য দাঁড়ানো, এবং আমরা উপায়ে নম্বর থেকে সরাতে গণনা করা হয় (0,0)করার (0,0)মধ্যে nধাপ। সেই গণনাটি তারপরে বা এর সাথে শুরু করতে 2পারে এমন অ্যাকাউন্টের দ্বারা অ্যাকাউন্টে বহুগুণ হবে ।A1-1

আমরা শূন্য পদক্ষেপ(x,y) হিসাবে থাকার স্থিতি

আমরা নন-শূন্য পদক্ষেপের সংখ্যা নিয়ে পুনরাবৃত্তি করি i, যা ফিরে পেতে এমনকি সমান হতে হবে (0,0)। অনুভূমিক এবং উল্লম্ব আন্দোলন দুটি স্বাধীন এক-মাত্রিক র্যান্ডম পেশা, যা গণনা করা যেতে পারে আপ করতে C(i,i/2)^2হয়, যেখানে C(n,k)দ্বিপদ সহগ হয়। ( kবাম দিকে পদক্ষেপ এবং kডানদিকের ধাপের সাথে হাঁটার C(2k,k)জন্য, পদক্ষেপের ক্রম চয়ন করার C(n,i)উপায় রয়েছে)) অতিরিক্তভাবে চালগুলি রাখার 4^(n-i)উপায় এবং শূন্য পদক্ষেপগুলি বেছে নেওয়ার উপায় রয়েছে। সুতরাং আমরা পেতে:

a(n) = 2 * sum_{i in (0,2,4,...,n)} C(i/2,i)^2 * C(n,i) * 4^(n-i)

এখন, আমাদের মূল সমস্যাটির দিকে ফিরে যাওয়া দরকার। কোনও শূন্য থাকলে কোনও রূপান্তরযোগ্য(A,B) হতে মঞ্জুরিপ্রাপ্ত জুটিকে সংজ্ঞা দিন । কোনও জোড়কে প্রায় অনুমোদনযোগ্য হিসাবে সংজ্ঞায়িত করুন যদি এবং দুটি ডট পণ্য উভয়ই শূন্য হয়।B(A,B)A[n+1] = -A[1]

লেমা: একটি প্রদত্ত ক্ষেত্রে n, প্রায় অনুমোদিতযোগ্য জুটি রূপান্তরিত জোড়গুলির সাথে এক থেকে একের সাথে যোগাযোগের হয়।

আমরা (reversibly) একটি পরিবর্তনীয় যুগল রূপান্তর করতে পারেন (A,B)একটি প্রায় মঞ্জুরিযোগ্য যুগল মধ্যে (A',B')negating দ্বারা A[m+1:]এবং B[m+1:], যেখানে mগত শুন্য সূচি B। এর জন্য পরীক্ষাটি সোজা হয়: শেষ উপাদানটি Bযদি শূন্য হয় তবে আমাদের কিছু করার দরকার নেই। অন্যথায়, আমরা যখন সর্বশেষ উপাদানটিকে প্রত্যাখ্যান করি তখন আমরা স্থানান্তরিত বিন্দু পণ্যের শেষ পদের সংরক্ষণের জন্য Aসর্বশেষ উপাদানটিকে তুচ্ছ করতে পারি B। তবে এটি অ-স্থানান্তরিত বিন্দু পণ্যটির সর্বশেষ মানটিকে অগ্রাহ্য করে, তাই এর দ্বিতীয় থেকে শেষ উপাদানটিকে উপেক্ষা করে আমরা এটি ঠিক করি A। তবে তারপরে এটি স্থানান্তরিত পণ্যের দ্বিতীয় থেকে শেষের মানটি ছুঁড়ে দেয়, তাই আমরা দ্বিতীয়-থেকে-শেষের উপাদানটিকে অগ্রাহ্য করি B। এবং তাই, একটি শূন্য উপাদান পৌঁছানো পর্যন্ত B

এখন, আমাদের কেবল এটি দেখানো দরকার যে প্রায় কোনও অনুমোদিত অনুমতিযুক্ত জুটি Bনেই যার জন্য একটি শূন্য নেই। ডট পণ্যের সমান শূন্যের জন্য, বাতিল করার জন্য আমাদের অবশ্যই একটি সমান সংখ্যা 1এবং -1শর্ত থাকতে হবে। প্রতিটি -1শব্দ গঠিত হয় (1,-1)বা (-1,1)। সুতরাং -1যে ঘটেছে সংখ্যার সমতা অনুযায়ী অনুযায়ী স্থির করা হয় n। যদি প্রথম এবং শেষ উপাদানগুলির মধ্যে Aপৃথক চিহ্ন থাকে তবে আমরা সমতা পরিবর্তন করি, তাই এটি অসম্ভব।

সুতরাং আমরা পেতে

c(n) = a(n)/2 if n is odd, else a(n)/2 + C(n,n/2)^2

p(n) = c(n) / 8^n

যা উপরোক্ত সূত্র দেয় (এর সাথে পুনরায় সূচি i' = i/2)।

আপডেট: একই সূত্রটি ব্যবহার করে এখানে একটি দ্রুত সংস্করণ দেওয়া হয়েছে:

from time import*
from itertools import*

def main():
    time_limit=time()+10

    binoms=[1]
    cb2s=[1]
    cb=1

    for n in count(1):
        if n&1:
            binoms=[a+b for a,b in zip([0]+binoms,binoms)]
        else:
            binoms=[a+b for a,b in zip([0]+binoms,binoms+[binoms[-1]])]
            cb=(cb<<2)-(cb+cb)/(n/2)
            cb2s.append(cb*cb)

        numer=0
        for i in xrange(n/2+1):
            t=cb2s[i]*binoms[min(2*i,n-2*i)]
            t<<=2*(n-2*i)
            numer+=t
        if not n&1:
            numer+=t
        e=(numer&-numer).bit_length()-1
        numer>>=e
        denom=1<<(3*n-e)

        if time()>time_limit:
            break

        print("%d %d/%d"%(n,numer,denom))

main()

অনুকূলিতকরণ কার্যকর করা হয়েছে:

  • ইনলাইন ফাংশন p(n)
  • দ্বিপদী সহগের C(n,k)সাথে পুনরাবৃত্তি ব্যবহার করুনk <= n/2
  • কেন্দ্রীয় দ্বিপদী সহগের জন্য পুনরাবৃত্তি ব্যবহার করুন

ঠিক তাই আপনি জানেন, p(n)একটি টুকরা দিক ফাংশন করা প্রয়োজন হবে না। সাধারণভাবে, যদি f(n) == {g(n) : n is odd; h(n) : n is even}আপনি লিখতে f(n) == (n-2*floor(n/2))*g(n) + ((n+1)-2*(floor((n+1)/2)))*h(n)বা n mod 2পরিবর্তে ব্যবহার করতে পারেন (n-2*floor(n/2))এখানে
mbomb007

1
@ mbomb007 এটি সুস্পষ্ট এবং উদ্বেগজনক।
মিচ শোয়ার্টজ

3

Min_25 এর সূত্রটির ব্যাখ্যা

Min_25 একটি দুর্দান্ত প্রমাণ পোস্ট করেছে তবে এটি অনুসরণ করতে কিছুটা সময় নিয়েছে। লাইনগুলির মধ্যে পূরণ করার জন্য এটি কিছুটা ব্যাখ্যা।

a (n, m) A [i] = A [i + 1] m বার এমন একটি নির্বাচন করার উপায়গুলি উপস্থাপন করে। একটি (এন, মি) এর সূত্রটি এনএম এর জন্য একটি (এন, এম) = {2 * (এন নির্বাচন এম) এর সমতুল্য; 0 এনএম বিজোড় জন্য} শুধুমাত্র একটি সাম্য অনুমোদিত কারণ A [i]! = A [i + 1] অবশ্যই একাধিকবার ঘটতে হবে যাতে A [0] = A [n]। 2 এর গুণকটি প্রাথমিক পছন্দ এ [0] = 1 বা এ [0] = -1 এর কারণে।

একবার (A [i]! = A [i + 1]) সংখ্যাটি q হিসাবে নির্ধারিত হয়ে গেলে (সি (এন) সূত্রে i নামকরণ করা হয়েছে), এটি দৈর্ঘ্যের q এবং nq এর দুটি 1D এলোমেলো পদক্ষেপে পৃথক হয়। খ (এম) হ'ল এক-মাত্রিক এলোমেলো পদক্ষেপের যে পদক্ষেপগুলি শুরু হয়েছিল একই স্থানে শেষ হয় এবং এতে বামে চলার 25% সম্ভাবনা রয়েছে, 50% স্থির থাকার সম্ভাবনা রয়েছে এবং 25% সম্ভাবনা রয়েছে ডানদিকে চলমান। উত্পাদক কার্যটি বর্ণনা করার আরও সুস্পষ্ট উপায় হ'ল [x ^ m] (1 + 2x + x ^ 2) ^ n, যেখানে 1, 2x এবং x ^ 2 যথাক্রমে বাম, কোন পদক্ষেপ এবং ডান উপস্থাপন করে। তবে তারপরে 1 + 2x + x ^ 2 = (x + 1) ^ 2।


তবুও পিপিসি ভালবাসার আর একটি কারণ! ধন্যবাদ.

2

সি ++

মিচ শোয়ার্টজের (সেরা) পাইথন উত্তরের একটি বন্দর। প্রাথমিক পার্থক্য হ'ল আমি ভেরিয়েবলের জন্য 2প্রতিনিধিত্ব করতাম এবং এর জন্য কিছু অনুরূপ করলাম, যা আমাকে একটি অ্যারে ব্যবহারের অনুমতি দেয়। এর সাথে ইন্টেল সি ++ ব্যবহার করে , পেয়েছি ! আমার প্রথম সংস্করণ পেয়েছে ।-1ab-O3N=141N=140

এটি বুস্ট ব্যবহার করে। আমি একটি সমান্তরাল সংস্করণ চেষ্টা করেছিলাম তবে কিছুটা সমস্যায় পড়েছি।

#include <boost/multiprecision/gmp.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/rational.hpp>
#include <boost/chrono.hpp>
#include <boost/array.hpp>
#include <iostream>
#include <utility>
#include <map>

typedef boost::multiprecision::mpz_int integer;
typedef boost::array<boost::array<std::map<int, std::map<int, integer> >, 3>, 2> array;
typedef boost::rational<integer> rational;

int main() {
    BOOST_AUTO(T, boost::chrono::high_resolution_clock::now());

    int N = 1;
    integer n = 1;
    array* Y = new array, *X = NULL;
    (*Y)[1][0][0][0] = 1;
    (*Y)[1][1][1][0] = 1;

    while (boost::chrono::high_resolution_clock::now() < T+boost::chrono::seconds(10)) {
        std::cout << N << " " << rational(n, boost::multiprecision::pow(integer(8), N)/4) << std::endl;
        ++N;
        delete X;
        X = Y;
        Y = new array;
        n = 0;

        for (int a=0; a<2; ++a)
            for (int b=0; b<3; ++b)
                for (BOOST_AUTO(s, (*X)[a][b].begin()); s != (*X)[a][b].end(); ++s)
                    for (BOOST_AUTO(t, s->second.begin()); t != s->second.end(); ++t) {
                        integer c = t->second;
                        int d = b&2 ? -1 : b, e = a == 0 ? -1 : a;

                        if (s->first == -1 && t->first+d+e == 0) n += c;
                        (*Y)[a][1][s->first+1][t->first+d] += c;

                        if (s->first == 1 && t->first-d+e == 0) n += c;
                        (*Y)[a][1][s->first-1][t->first-d] += c;

                        if (s->first == 1 && t->first+d-e == 0) n += c;
                        (*Y)[a][2][s->first-1][t->first+d] += c;

                        if (s->first == -1 && t->first-d-e == 0) n += c;
                        (*Y)[a][2][s->first+1][t->first-d] += c;

                        c *= 2;

                        if (s->first == 0 && t->first+d == 0) n += c;
                        (*Y)[a][0][s->first][t->first+d] += c;

                        if (s->first == 0 && t->first-d == 0) n += c;
                        (*Y)[a][0][s->first][t->first-d] += c;
                    }
    }

    delete X;
    delete Y;
}

এটি g++ -O3 kirbyfan64sos.cpp -o kirbyfan64sos -lboost_system -lboost_timer -lboost_chrono -lrt -lgmpসংকলন করা প্রয়োজন। (অ্যাডিটসুকে ধন্যবাদ।)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.