সমস্ত উপগ্রহের পণ্য নিতে দ্রুততম অ্যালগরিদম


23

nএকটি অ্যারেতে দেওয়া নম্বরগুলি (আপনি ধরে নিতে পারবেন না যে তারা পূর্ণসংখ্যার), আমি আকারের সমস্ত উপসর্গের পণ্যটি গণনা করতে চাই n-1

আপনি যতগুলি সংখ্যার শূন্য না হন ততক্ষণ প্রতিটি সংখ্যা এক সাথে গুণ করে এবং তারপরে প্রতিটি দ্বারা বিভাজন করে এটি করতে পারেন। যাইহোক, আপনি কত তাড়াতাড়ি কোনও বিভাগ ছাড়াই এটি করতে পারেন?

আপনি যদি বিভাগকে অনুমতি না দিয়ে থাকেন, তবে এন-1 আকারের সমস্ত উপসর্গের গুণনটির জন্য গণিতের অপারেশনগুলির সর্বনিম্ন সংখ্যা (যেমন গুণ এবং সংযোজন) কী প্রয়োজন?

স্পষ্টতই আপনি এটি (n-1)*nবহুগুণে করতে পারেন ।

স্পষ্ট করার জন্য, আউটপুটটি nবিভিন্ন পণ্য এবং মেমরিটিতে পড়া এবং লেখা ব্যতীত কেবল অপারেশনগুলি হ'ল গুণ, সংযোজন এবং বিয়োগফল।

উদাহরণ

ইনপুট তিন নম্বর থাকে 2,3,5, তাহলে আউটপুট তিনটি সংখ্যার 15 = 3*5, 10 = 2*5এবং 6 = 2*3

বিজয়ী মানদণ্ড

উত্তরগুলির গাণিতিক ক্রিয়াকলাপগুলির সংখ্যার জন্য একটি সঠিক সূত্র দেওয়া উচিত যা তাদের কোড অনুসারে ব্যবহার করবে n। জীবনকে সহজ করে তুলতে, আমি কেবলমাত্র n = 1000আপনার সূত্রটির স্কোর বিচার করার জন্য প্লাগ ইন করব । কম তত ভাল।

যদি আপনার কোডটির জন্য সঠিক সূত্র তৈরি করা খুব কঠিন হয় তবে আপনি n = 1000কোডটিতে পাটিগণিত ক্রিয়াকলাপের জন্য এটি চালনা এবং গণনা করতে পারেন । একটি সঠিক সূত্র তবে সেরা হবে।

n=1000সহজ তুলনা করার জন্য আপনার উত্তরটির জন্য আপনার স্কোর যুক্ত করা উচিত ।


4
আমরা কি 1 কে নিখরচায় গুণতে পারি? অন্যথায় আমি একটি কাস্টম-গুণিত ফাংশন সংজ্ঞায়িত করব যা এটি করে।
xnor

3
পর্যাপ্ত পরিমাণে স্পেসার 0 সংখ্যার সাথে একত্রে সংখ্যার সাথে সমান্তরালভাবে সম্পূর্ণ গুণের বহুগুণ করা কি নিয়মের বিরুদ্ধে হবে?
xnor

1
যেমন অপারেশন না +উপর সূচকের গণনা? যদি এটি হয় তবে অ্যারে সূচকগুলিও গণনা করে? (যেহেতু এটি সংযোজন এবং নির্ধারণের জন্য সমস্ত সিনট্যাকটিক চিনির পরে)।
নর

2
@ অন্য ঠিক আছে আমি দিচ্ছি :) কেবল গণিতের অপারেশনগুলি গণনা করুন যা কোনওভাবে ইনপুটকে জড়িত করে।
আর্থার

1
স্পষ্টত আপনি এটা করতে পারেন (n-1)*nmultiplications আপনি বলতে চাচ্ছেন (n-2)*n, ঠিক?
লুইস মেন্ডো

উত্তর:


25

পাইথন, 3 (এন -2) ক্রিয়াকলাপ, স্কোর = 2994

l = list(map(float, input().split()))
n = len(l)

left = [0] * len(l)
right = [0] * len(l)
left[0] = l[0]
right[-1] = l[-1]
for i in range(1,len(l)-1):
  left[i] = l[i] * left[i - 1]
  right[-i-1] = l[-i-1] * right[-i]

result = [0] * len(l)
result[-1] = left[-2]
result[0] = right[1]
for i in range(1, len(l) - 1):
  result[i] = left[i - 1] * right[i+1]

print(result)

অ্যারেগুলিতে leftএবং rightযথাক্রমে বাম থেকে এবং ডান থেকে অ্যারের জমে থাকা পণ্যগুলি থাকে।

সম্পাদনা: প্রমাণ যে 3 (n-2) হ'ল n> = 2 এর জন্য প্রয়োজনীয় অপারেশনগুলির সর্বোত্তম সংখ্যা, যদি আমরা কেবলমাত্র গুণটি ব্যবহার করি lic

আমরা এটি অন্তর্ভুক্তির মাধ্যমে করব; উপরের অ্যালগরিদম দ্বারা, আমরা কেবল প্রমাণ করতে হবে যে এন> = 2, 3 (এন-2) এর জন্য প্রয়োজনীয় গুণনের সংখ্যার উপর একটি নিম্ন সীমাবদ্ধ।

এন = 2 এর জন্য আমাদের কমপক্ষে 0 = 3 (2-2) গুণ করা দরকার, ফলে ফলাফলটি তুচ্ছ।

এন> 2, এবং ধরুন এন - 1 উপাদানগুলির জন্য আমাদের কমপক্ষে 3 (এন -3) গুণ করা দরকার। কে গুণক সহ এন উপাদানগুলির একটি সমাধান বিবেচনা করুন। এখন, আমরা এই উপাদানগুলির মধ্যে সর্বশেষটি সরিয়ে দিচ্ছি যেন এটি 1 ছিল এবং এটির মাধ্যমে সমস্ত গুণগুলি সরাসরি সরল করে। আমরা অন্যান্য সমস্ত উপাদানগুলির উত্পাদনের দিকে নিয়ে যাওয়া গুণকেও সরিয়ে ফেলি, যেহেতু এটির প্রয়োজন হয় না কারণ এটি অন্য উপাদানগুলির এন -2 এর পণ্য পেতে কোনও মধ্যবর্তী মান হিসাবে কখনই ব্যবহার করা যায় না, কারণ বিভাগের অনুমতি নেই। এটি আমাদেরকে l গুণক এবং n - 1 উপাদানগুলির জন্য একটি সমাধান দেয় leaves

আনয়ন অনুমান দ্বারা, আমরা l> = 3 (এন -3) আছে।

এখন, আসুন একবার দেখে নেওয়া যাক কত গুণগুলি সরানো হয়েছিল। এর মধ্যে একটি হ'ল সর্বশেষ ব্যতীত সমস্ত উপাদানগুলির পণ্যটির দিকে পরিচালিত। তদুপরি, সর্বশেষ উপাদানটি কমপক্ষে দুটি গুণে সরাসরি ব্যবহৃত হত: যদি এটি শুধুমাত্র একটিতে ব্যবহৃত হয়, তবে এটি অন্য উপাদানগুলির কিছু পণ্য নিয়ে অন্তর্বর্তী ফলাফল দ্বারা গুণিতকালে ব্যবহৃত হত; যাক, সাধারণতার ক্ষতি ছাড়াই, এই মধ্যবর্তী ফলাফলটি পণ্যটিতে প্রথম উপাদানকে অন্তর্ভুক্ত করে। তারপরে, সমস্ত উপাদানগুলির পণ্য পাওয়ার কোনও উপায় নেই তবে প্রথমটি, যেহেতু প্রতিটি উপাদান যেখানে শেষ উপাদান থাকে তা হয় হয় সর্বশেষ উপাদান, বা এতে প্রথম উপাদান থাকে।

আমাদের এইভাবে দাবি> উপপাদ্য প্রমাণ করে কে> = l + 3> = 3 (এন -২) রয়েছে।


8
এই সক্রিয় আউট মধ্যে Haskell খুব পরিষ্কার : f l = zipWith (*) (scanl (*) 1 l) (scanr (*) 1 $ tail l)
xnor

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

12

হাস্কেল , স্কোর 2994

group :: Num a => [a] -> [[a]]
group (a:b:t) = [a,b] : group t
group [a] = [[a]]
group [] = []

(%) :: (Num a, Eq a) => a -> a -> a
a % 1 = a
1 % b = b
a % b = a * b

prod_one_or_two :: (Num a, Eq a) => [a] -> a
prod_one_or_two [a, b] = a % b
prod_one_or_two [x] = x

insert_new_value :: (Num a, Eq a) => ([a], a) -> [a]
insert_new_value ([a, b], c) = [c % b, c % a]
insert_new_value ([x], c) = [c]

products_but_one :: (Num a, Eq a) => [a] -> [a]
products_but_one [a] = [1]
products_but_one l = 
    do combination <- combinations ; insert_new_value combination
    where 
        pairs = group l
        subresults = products_but_one $ map prod_one_or_two pairs
        combinations = zip pairs subresults

এটি অনলাইন চেষ্টা করুন!

বলুন আমাদের তালিকা দেওয়া হয়েছে [a,b,c,d,e,f,g,h]। আমরা প্রথমে এটি জোড়া মধ্যে গ্রুপ [[a,b],[c,d],[e,f],[g,h]]। তারপরে, আমরা pairsতাদের পণ্যগুলির অর্ধ-আকারের তালিকার পুনরাবৃত্তি করিsubresults

[a*b, c*d, e*f, g*h] -> [(c*d)*(e*f)*(g*h), (a*b)*(e*f)*(g*h), (a*b)*(c*d)*(g*h), (a*b)*(c*d)*(e*f)]

আমরা প্রথম উপাদান না নেন তাহলে (c*d)*(e*f)*(g*h), এবং সংখ্যাবৃদ্ধি এটি দ্বারা bএবং aযথাক্রমে, আমরা সব কিন্তু গুণফল পেতে aএবং সব কিন্তু b। প্রতিটি জুটির জন্য এটি করা এবং সেই জুটিটি হারিয়ে যাওয়ার সাথে পুনরাবৃত্তির ফলস্বরূপ, আমরা চূড়ান্ত ফলাফল পেয়েছি। বিজোড় দৈর্ঘ্যের কেসটি বিশেষভাবে পরিচালনা করা হয় বিজোড় উপাদানটি পুনরাবৃত্তিমূলক পদক্ষেপে অযৌক্তিকভাবে পাস করে দেওয়া হয়, এবং অবশিষ্ট উপাদানগুলির পণ্যটি এটি ছাড়া পণ্য হয়।

Multiplications সংখ্যা t(n)হয় n/2, পেয়ারিং পণ্যের জন্য t(n/2)recursive কল জন্য, এবং অন্য nপৃথক উপাদানের সঙ্গে পণ্যের জন্য। এটি t(n) = 1.5 * n + t(n/2)বিজোড় জন্য দেয় n। বিজোড় জন্য একটি আরো সঠিক সংখ্যা ব্যবহার nএবং গুন উপেক্ষা 1জন্য বেস কেস স্কোর দেয় 2997জন্য n=1000


এই খুব সুন্দর.
আর্থার

আমি মনে করি যে আমার উত্তর হিসাবে স্কোরটি 2995 এবং 2994 না হওয়ার কারণ হ'ল এটি দুটি সংখ্যার অ-বিদ্যুতের ক্ষেত্রে সমস্ত সংখ্যার গুণাগুণ গণনা করে, যা পরে কেটে গেছে। products_but_one'সঠিক কোনও দৈর্ঘ্য ফিরিয়ে দেওয়ার মাধ্যমে কোনও সাবধানতার সাথে পরিচালনা করা এড়াতে পারে।
nore

@ অন্য আমি দেখতে পেলাম আমার গণনায় আমার একটি অতিরিক্ত গুণ রয়েছে কারণ আমি ভুলে গেছি বেস কেসটিতে এমন একটি গুণ রয়েছে 1যা গুণ করা যায়। আমি মনে করি প্যাডিং 1 জিনিসগুলিতে কোনও প্রভাব ফেলেনি, তবে আমি সেগুলি ব্যবহার না করার জন্য আমার অ্যালগরিদম পরিষ্কার করেছি।
xnor

এই কোডটি কি অনুমান করে যে ইনপুটটি পূর্ণসংখ্যা হয়?

@ ল্যাম্বিক এটি করে তবে কেবলমাত্র typeচ্ছিক ধরণের টীকায়। আমি তাদের সব পরিবর্তন করব float
xnor

9

হাস্কেল , স্কোর 9974

partition :: [Float] -> ([Float], [Float])
partition = foldr (\a (l1,l2) -> (l2, a:l1)) ([],[])

(%) :: Float -> Float -> Float
a % 1 = a
1 % b = b
a % b = a*b

merge :: (Float, [Float]) -> (Float, [Float]) -> (Float, [Float])
merge (p1,r1) (p2, r2) = (p1%p2, map(%p1)r2 ++ map(%p2)r1)

missing_products' :: [Float] -> (Float, [Float])
missing_products' [a] = (a,[1])
missing_products' l = merge res1 res2
    where
        (l1, l2) = partition l
        res1 = missing_products' l1
        res2 = missing_products' l2

missing_products :: [Float] -> [Float]
missing_products = snd . missing_products'

এটি অনলাইন চেষ্টা করুন!

একটি বিভাজন এবং বিজয়ী কৌশল, মার্জ সাজানোর খুব স্মরণ করিয়ে দেয়। কোনও ইনডেক্সিং করে না।

ফাংশনটি partitionপার্টিশনের বিপরীত দিকগুলিতে বিকল্প উপাদান স্থাপন করে তালিকাটিকে সমান-সমান-অর্ধেক অংশে বিভক্ত করে। আমরা (p,r)প্রতিটি অংশের জন্য পুনরাবৃত্তভাবে ফলাফলগুলি rএকের সাথে নিখোঁজ এবং pসামগ্রিক পণ্যগুলির তালিকাতে একত্রীকরণ করি ।

সম্পূর্ণ তালিকার আউটপুটের জন্য, অনুপস্থিত উপাদানটি অবশ্যই একটি অর্ধেকের মধ্যে থাকা উচিত। যে উপাদানটি অনুপস্থিত রয়েছে সেটির অর্ধেকের জন্য একটি এক-অনুপস্থিত-পণ্য, অন্য অর্ধের জন্য সম্পূর্ণ পণ্য দ্বারা গুণিত। সুতরাং, আমরা প্রতিটি অর্ধেকের সম্পূর্ণ পণ্য দ্বারা এক-অনুপস্থিত-সহ গুন করি এবং ফলাফলগুলির একটি তালিকা তৈরি করি, যেমন map(*p1)r2 ++ map(*p2)r1)। এটি দৈর্ঘ্য nযেখানে গুণ, লাগে np1*p2ভবিষ্যতে ব্যবহারের জন্য আমাদের আরও 1 গুণফলের জন্য একটি নতুন পূর্ণ পণ্য তৈরি করতে হবে ।

এই অপারেশনের সংখ্যার জন্য সাধারণ পুনরাবৃত্তির দেয় t(n)সঙ্গে nএমনকি:t(n) = n + 1 + 2 * t(n/2) । বিজোড় একটি অনুরূপ, তবে সাবলিস্টগুলির মধ্যে একটি 1বৃহত্তর। পুনরাবৃত্তিটি সম্পাদন করে, আমরা n*(log_2(n) + 1)গুণগুলি পাই , যদিও বিজোড় / এমনকি পার্থক্যটি সঠিক মানটিকে প্রভাবিত করে। মান পর্যন্ত t(3)দ্বারা গুন না করে উন্নত হয় 1একটি বৈকল্পিক সংজ্ঞা দ্বারা (%)এর (*)যে শর্টকাট _*1বা 1*_মামলা।

এটি এর 9975জন্য গুণগুলি দেয় n=1000। আমি বিশ্বাস করি হাস্কেলের অলসতার অর্থ বাইরের স্তরের অব্যবহৃত সামগ্রিক পণ্য গণনা করা হয় না 9974; যদি আমি ভুল করে থাকি তবে আমি এটিকে স্পষ্টভাবে বাদ দিতে পারি।


আপনি এক মিনিট আগে টাইমস্ট্যাম্প দ্বারা আমাকে মারধর।
নোর

যদি সূত্রটি ঠিকঠাকভাবে কাজ করা শক্ত হয় তবে নিখরচায় এটিকে চালানো n = 1000এবং কোডটিতে পাটিগণিত ক্রিয়াকলাপ গণনা করুন।
আর্থার

যেহেতু আমাদের কোডটি মূলত একই, তাই আপনি বুঝতে পারছেন না যে আপনি কীভাবে পেয়েছেন 9974এবং কীভাবে (বহিরাগত স্তরের সামগ্রিক পণ্যকে গণনা করার ক্ষেত্রে) 9975গুণন করতে পারেন না n = 1000। আপনি 1যে ইনপুটটিকে এটি পরীক্ষার জন্য ব্যবহার করেছেন সেটিতে কি কোনও অন্তর্ভুক্ত করেছিলেন?
নর

@Nore আপনি ঠিক বলেছেন, আমি একজনের কাছাকাছি ছিলাম। আমি বহুগুণ ফাংশন কলগুলির সংখ্যার জন্য পুনরাবৃত্তি করতে কোড লিখেছি। সরাসরি কল গণনা করা আরও নির্ভরযোগ্য হবে - কেউ কি জানেন যে আমি হাসকেলে এটি কীভাবে করব?
xnor

1
@xnor আপনি ব্যবহার করতে পারেন traceথেকে Debug.Traceএকটি ধরা-সব | trace "call!" False = undefinedপাহারা, আমি মনে করি। তবে unsafePerformIOএটি হুডের নীচে ব্যবহার করে, সুতরাং এটি আসলে তেমন কোনও উন্নতি নয়।
সোহম চৌধুরী

6

হাস্কেল , স্কোর 2994

group :: [a] -> Either [(a, a)] (a, [(a, a)])
group [] = Left []
group (a : l) = case group l of
  Left pairs -> Right (a, pairs)
  Right (b, pairs) -> Left ((a, b) : pairs)

products_but_one :: Num a => [a] -> [a]
products_but_one [_] = [1]
products_but_one [a, b] = [b, a]
products_but_one l = case group l of
  Left pairs ->
    let subresults =
          products_but_one [a * b | (a, b) <- pairs]
    in do ((a, b), c) <- zip pairs subresults; [c * b, c * a]
  Right (extra, pairs) ->
    let subresult : subresults =
          products_but_one (extra : [a * b | (a, b) <- pairs])
    in subresult : do ((a, b), c) <- zip pairs subresults; [c * b, c * a]

এটি অনলাইন চেষ্টা করুন!

কিভাবে এটা কাজ করে

এটি এক্সনোরের অ্যালগরিদমের একটি ক্লিন আপ সংস্করণ যা বিজোড় কেসটিকে আরও সহজবোধ্যভাবে মোকাবেলা করে (সম্পাদনা করুন: দেখে মনে হচ্ছে xnor এটি একইভাবে পরিষ্কার করেছে):

[ক, খ, সি, ডি, ই, এফ, জি] ↦
[ক, বিসি, ডি, এফজি] ↦
[(বিসি) (ডি) (এফজি), এ (ডি) (এফজি), এ (বিসি) ( fg), a (বিসি) (ডি)] পুনরাবৃত্তি দ্বারা ↦
[(বিসি) (ডি) (এফজি), ক (ডি) (এফজি) সি, এ (ডি) (এফজি) বি, ক (বিসি) (এফজি) e, a (bc) (fg) d, a (bc) (de) g, a (bc) (de) f]

[ক, খ, সি, ডি, ই, এফ, জি, এইচ] ↦
[আব, সিডি, এফ, ঘ] ↦
[(সিডি) (ইফ) (ঘ), (আব) (ইফ) (ঘ), ( আব) (সিডি) (ঘ), (আব) (সিডি) (ইফ)] পুনরাবৃত্তি দ্বারা ↦
[(সিডি) (ইফ) (ঘ) বি, (সিডি) (ইফ) (ঘ) ক, (আব) (ইফ) ) (ঘ) ডি, (আব) (ইফ) (ঘ) সি, (আব) (সিডি) (ঘ) চ, (আব) (সিডি) (ঘ) ই, (আব) (সিডি) (এফ) এইচ, (AB) (সিডি) (EF) ছ]।


"একটি অ্যারেতে n নম্বর দেওয়া (আপনি তারা পূর্ণসংখ্যা বলে ধরে নিতে পারবেন না)," আমরা ধরে নিতে পারি না যে তারা পূর্ণসংখ্যা

5

ও (এন লগ এন) ক্রিয়াকলাপ, স্কোর = 9974

বাইনারি গাছের সাথে কাজ করে।

পাইথন

l = list(map(int, input().split()))
n = len(l)

p = [0] * n + l
for i in range(n - 1, 1, -1):
  p[i] = p[i + i] * p[i + i+1]

def mul(x, y):
  if y == None:
    return x
  return x * y

r = [None] * n + [[None]] * n
for i in range(n - 1, 0, -1):
  r[i] = [mul(p[i + i + 1], x) for x in r[i + i]] + [mul(p[i + i], x) for x in r[i + i + 1]]

u = r[1]
j = 1
while j <= n:
  j += j
print(u[n+n-j:] + u[:n+n-j])

এর জন্য তালিকা সংযোজন অপারেশন এবং সংখ্যায় কিছু গাণিতিক প্রয়োজন যা ইনপুট মান নয়; নিশ্চিত যে নিশ্চিত না। mulফাংশন সেখানে সংরক্ষণ এন অপারেশন বেস মামলা, 1 দ্বারা গুন কোন ক্ষেত্রে তাদের নষ্ট এড়াতে হয়, এই হে (n log n) অপারেশন হয়। সঠিক সূত্রটি হ'ল, যদি কেবল ইনপুট সংখ্যায় পাটিগণিত অপারেশনগুলি গণনা করা হয় j = floor(log_2(n)): j * (2^(j + 1) - n) + (j + 1) * (2 * n - 2^(j + 1)) - 2

বাহ্যিক পণ্যকে গণনা না করার ধারণা দিয়ে একটি অপারেশন বাঁচানোর জন্য @ এক্সনোরকে ধন্যবাদ!

শেষ অংশটি নিখোঁজ শর্ত অনুসারে পণ্যগুলি আউটপুট দেয়।


যদি সূত্রটি ঠিকঠাকভাবে কাজ করা শক্ত হয় তবে নিখরচায় এটিকে চালানো n = 1000এবং কোডটিতে পাটিগণিত ক্রিয়াকলাপ গণনা করুন।
আর্থার

আমি 10975 অপারেশন গণনা করেছি ...?
হাইপারনিউটারিনো

p[i] = p[i + i] * p[i + i+1]গণনা করা হয়নি
হাইপারনিউটারিনো

এটি n log2 n + nঅপারেশনগুলি সম্পর্কে (যা ও (
নলগন

@ হাইপার নিউট্রিনো-এর অপারেশনগুলি p[i] = p[i + i] * p[i + i + 1]গুণক অপটিমাইজেশন দ্বারা সংরক্ষণ করা উচিত। তবে আমি হয়ত অনেককেই গণনা করতে পারি।
নর

3

O ((n-2) * n) = O (n 2 ): তুচ্ছ সমাধান

এটি কেবলমাত্র তুচ্ছ সমাধান যা প্রতিটি উপশমের একসাথে একসাথে:

পাইথন

def product(array): # Requires len(array) - 1 multiplication operations
    if not array: return 1
    result = array[0]
    for value in array[1:]:
        result *= value
    return result

def getSubsetProducts(array):
    products = []
    for index in range(len(array)): # calls product len(array) times, each time calling on an array of size len(array) - 1, which means len(array) - 2 multiplication operations called len(array) times
        products.append(product(array[:index] + array[index + 1:]))
    return products

নোট করুন যে এটির জন্য nতালিকা-সংযোজন অপারেশনগুলিও প্রয়োজন; নিশ্চিত যে নিশ্চিত না। যদি এটি অনুমোদিত না হয় তবে তারপরে product(array[:index] + array[index + 1:])প্রতিস্থাপন করা যেতে পারে product(array[:index]) * product(array[index + 1:])যা সূত্রে পরিবর্তন করে O((n-1)*n)


উত্তরে আপনি নিজের স্কোর যুক্ত করতে পারেন। 998 * 1000 এই ক্ষেত্রে।
আর্থার

আপনার productফাংশন O(n)ক্রিয়াকলাপগুলির প্রয়োজন নেই ? অ্যারেতে প্রতিটি উপাদানগুলির জন্য একটি (এটিকে সহজেই পরিবর্তন করা যায় O(n-1))
রোমান গ্রাফ

@ রোমানগ্রাফ সত্য আমি এটিকে ও (N-1) এ পরিবর্তন করব তবে এটি নির্দেশ করার জন্য ধন্যবাদ।
হাইপারনিউটারিনো

এটি এটমিক-কোড-গল্ফে পরিবর্তন করা হয়েছে ...
এরিক দি আউটগলফার

@ এরিকথ আউটগল্ফার এটি এখন আমার স্কোরকে কী করে? আমি নির্মোহভাবে বোকা না হয়ে থাকলে ট্যাগ এবং চশমাগুলি এখন একে অপরের সাথে বিরোধিতা করে না?
হাইপারনিউটারিনো

3

পাইথন, 7540

একটি ত্রিপক্ষীয় মার্জ কৌশল আমি মনে করি আমি আরও বড় একত্রিত হয়ে আমি এর থেকে আরও ভাল করতে পারি। এটি ও (এন লগ এন)।

সম্পাদনা: একটি ভুল হিসাব ঠিক করা হয়েছে।

count = 0
def prod(a, b):
    if a == 1: return b
    if b == 1: return a
    global count
    count += 1
    return a * b

def tri_merge(subs1, subs2, subs3):
    total1, missing1 = subs1
    total2, missing2 = subs2
    total3, missing3 = subs3

    prod12 = prod(total1, total2)
    prod13 = prod(total1, total3)
    prod23 = prod(total2, total3)

    new_missing1 = [prod(m1, prod23) for m1 in missing1]
    new_missing2 = [prod(m2, prod13) for m2 in missing2]
    new_missing3 = [prod(m3, prod12) for m3 in missing3]

    return prod(prod12, total3), new_missing1 + new_missing2 + new_missing3

def tri_partition(nums):
    split_size = len(nums) // 3
    a = nums[:split_size]
    second_split_length = split_size + (len(nums) % 3 == 2)
    b = nums[split_size:split_size + second_split_length]
    c = nums[split_size + second_split_length:]
    return a, b, c

def missing_products(nums):
    if len(nums) == 1: return nums[0], [1]
    if len(nums) == 0: return 1, []
    subs = [missing_products(part) for part in tri_partition(nums)]
    return tri_merge(*subs)

def verify(nums, res):
    actual_product = 1
    for num in nums:
        actual_product *= num
    actual_missing = [actual_product // num for num in nums]
    return actual_missing == res[1] and actual_product == res[0]

nums = range(2, int(input()) + 2)
res = missing_products(nums)

print("Verified?", verify(nums, res))
if max(res[1]) <= 10**10: print(res[1])

print(len(nums), count)

প্রাসঙ্গিক ফাংশনটি হ'ল missing_productsযা সামগ্রিক পণ্য এবং সমস্ত অনুপস্থিত উপাদান সরবরাহ করে।


আপনি কি গুণগুণ গণনা করেছেন tri_merge? এছাড়াও আপনি 2 * split_size + ...এর tri_partitionসাথে প্রতিস্থাপন করতে পারেন split_size + split_size + ...
রোমান গ্রাফ

@ রোমানগ্রাফ আপনার পরামর্শ অনুসারে আমি এটি পুনর্গঠন করেছি।
isaacg

1

ডিসি, স্কোর 2994

#!/usr/bin/dc -f

# How it works:
# The required products are
#
#   (b × c × d × e × ... × x × y × z)
# (a) × (c × d × e × ... × x × y × z)
# (a × b) × (d × e × ... × x × y × z)
# ...
# (a × b × c × d × e × ... × x) × (z)
# (a × b × c × d × e × ... × x × y)
#
# We calculate each parenthesised term by
# multiplying the one above (on the left) or below
# (on the right), for 2(n-2) calculations, followed
# by the n-2 non-parenthesised multiplications
# giving a total of 3(n-2) operations.

# Read input from stdin
?

# We will store input values into stack 'a' and
# accumulated product into stack 'b'.  Initialise
# stack b with the last value read.
sb

# Turnaround function at limit of recursion: print
# accumulated 'b' value (containing b..z above).
[Lbn[ ]nq]sG

# Recursive function - on the way in, we stack up
# 'a' values and multiply up the 'b' values.  On
# the way out, we multiply up the 'a' values and
# multiply each by the corresponding 'b' value.
[dSalb*Sb
z1=G
lFx
dLb*n[ ]n
La*]dsFx

# Do the last a*b multiplication
dLb*n[ ]n

# And we have one final 'a' value that doesn't have a
# corresponding 'b':
La*n

আমি ধরে নিচ্ছি যে পূর্ণসংখ্যার তুলনা z1=(যা আমরা শেষ মানের কাছে পৌঁছালে পুনরাবৃত্তিটি শেষ করে) নিখরচায়। এটি foreachঅন্যান্য ভাষার পছন্দগুলির সমতুল্য ।

মিছিল!

for i in '2 3 5' '2 3 5 7' '0 2 3 5' '0 0 1 2 3 4'
do printf '%s => ' "$i"; ./127147.dc <<<"$i"; echo
done
2 3 5 => 15 10 6
2 3 5 7 => 105 70 42 30
0 2 3 5 => 30 0 0 0
0 0 1 2 3 4 => 0 0 0 0 0 0

বড় এবং ছোট ইনপুট সহ একটি ডেমো:

./127147.dc <<<'.0000000000000000000542101086242752217003726400434970855712890625 1 18446744073709551616'
18446744073709551616 1.0000000000000000000000000000000000000000000000000000000000000000 .0000000000000000000542101086242752217003726400434970855712890625

1

সি ++, স্কোর: 5990, ও ([2NlogN] / 3)

এই বাস্তবায়নে বাইনারি ট্রি লুক আপ টেবিল ব্যবহার করা হয়। আমার প্রথম বাস্তবায়নটি হ'ল (এনলগএন), তবে শেষ মুহুর্তের একটি অপ্টিমাইজেশন যা সমস্ত অ্যারে উপাদানকে বিয়োগের জুটি দ্বারা বিভক্ত করে, + 2 গুণগুলি দিনটি সংরক্ষণ করে। আমি মনে করি এটি এখনও আরও কিছুটা আরও অনুকূল করা যেতে পারে, সম্ভবত আরও 16% ...

আমি কিছু ডিবাগিং ট্রেসগুলিতে রেখেছি, কেবল কারণ এগুলি মুছে ফেলা সহজ তাদের পুনর্লিখনের চেয়ে :)

[সম্পাদনা] 100 এর জন্য ও ([2NlogN] / 3) এ প্রকৃত জটিলতা পরিমাপ করা হয় small 1 মিলিয়ন উপাদানের এ সেট জন্য খুব বড় হে (0.57.NlogN)

#include "stdafx.h"
#include <vector>
#include <iostream>
#include <random>
#include <cstdlib>

using DataType = long double;

using DataVector = std::vector<DataType>;

struct ProductTree
{
    std::vector<DataVector> tree_;
    size_t ops_{ 0 };

    ProductTree(const DataVector& v) : ProductTree(v.begin(), v.end()) {}
    ProductTree(DataVector::const_iterator first, DataVector::const_iterator last)
    {
        Build(first, last);
    }

    void Build(DataVector::const_iterator first, DataVector::const_iterator last)
    {
        tree_.emplace_back(DataVector(first, last));

        auto size = std::distance(first, last);
        for (auto n = size; n >= 2; n >>= 1)
        {
            first = tree_.back().begin();
            last = tree_.back().end();

            DataVector v;
            v.reserve(n);
            while (first != last) // steps in pairs
            {
                auto x = *(first++);
                if (first != last)
                {
                    ++ops_;
                    x *= *(first++); // could optimize this out,small gain
                }
                v.push_back(x);
            }
            tree_.emplace_back(v);
        }
    }

    // O(NlogN) implementation... 
    DataVector Prod()
    {
        DataVector result(tree_[0].size());
        for (size_t i = 0; i < tree_[0].size(); ++i)
        {
            auto depth = tree_.size() - 1;
            auto k = i >> depth;
            result[i] = ProductAtDepth(i, depth);
        }
        return result;
    }

    DataType ProductAtDepth(size_t index, size_t depth) 
    {
        if (depth == 0)
        {
            return ((index ^ 1) < tree_[depth].size())
                ? tree_[depth][index ^ 1]
                : 1;
        }
        auto k = (index >> depth) ^ 1;

        if ((k < tree_[depth].size()))
        {
            ++ops_;
            return tree_[depth][k] * ProductAtDepth(index, depth - 1);
        }
        return ProductAtDepth(index, depth - 1);
    }    

    // O([3NlogN]/2) implementation... 
    DataVector Prod2()
    {
        DataVector result(tree_[0].size());
        for (size_t i = 0; i < tree_[0].size(); ++i)    // steps in pairs
        {
            auto depth = tree_.size() - 1;
            auto k = i >> depth;
            auto x = ProductAtDepth2(i, depth);
            if (i + 1 < tree_[0].size())
            {
                ops_ += 2;
                result[i + 1] = tree_[0][i] * x;
                result[i] = tree_[0][i + 1] * x;
                ++i;
            }
            else
            {
                result[i] = x;
            }
        }
        return result;
    }

    DataType ProductAtDepth2(size_t index, size_t depth)
    {
        if (depth == 1)
        {
            index = (index >> 1) ^ 1;
            return (index < tree_[depth].size())
                ? tree_[depth][index]
                : 1;
        }
        auto k = (index >> depth) ^ 1;

        if ((k < tree_[depth].size()))
        {
            ++ops_;
            return tree_[depth][k] * ProductAtDepth2(index, depth - 1);
        }
        return ProductAtDepth2(index, depth - 1);
    }

};


int main()
{
    //srand(time());

    DataVector data;
    for (int i = 0; i < 1000; ++i)
    {
        auto x = rand() & 0x3;          // avoiding overflow and zero vaolues for testing
        data.push_back((x) ? x : 1);
    }

    //for (int i = 0; i < 6; ++i)
    //{
    //  data.push_back(i + 1);
    //}

    //std::cout << "data:[";
    //for (auto val : data)
    //{
    //  std::cout << val << ",";
    //}
    //std::cout << "]\n";

    ProductTree pt(data);
    DataVector result = pt.Prod2();

    //std::cout << "result:[";
    //for (auto val : result)
    //{
    //  std::cout << val << ",";
    //}
    //std::cout << "]\n";
    std::cout << "N = " << data.size() << " Operations :" << pt.ops_ << '\n';

    pt.ops_ = 0;
    result = pt.Prod();

    //std::cout << "result:[";
    //for (auto val : result)
    //{
    //  std::cout << val << ",";
    //}
    //std::cout << "]\n";

    std::cout << "N = " << data.size() << " Operations :" << pt.ops_ << '\n';

    return 0;
}

আমি সম্পূর্ণরূপে @ নুরের অ্যালগরিদম যুক্ত করছি। এটি সত্যিই দুর্দান্ত, এবং দ্রুততম।

class ProductFlat
{
private:
    size_t ops_{ 0 };

    void InitTables(const DataVector& v, DataVector& left, DataVector& right)
    {
        if (v.size() < 2)
        {
            return;
        }

        left.resize(v.size() - 1);
        right.resize(v.size() - 1);

        auto l = left.begin();
        auto r = right.rbegin();
        auto ol = v.begin();
        auto or = v.rbegin();

        *l = *ol++;
        *r = *or++;
        if (ol == v.end())
        {
            return;
        }

        while (ol + 1 != v.end())
        {
            ops_ += 2;
            *l = *l++ * *ol++;
            *r = *r++ * *or++;
        }
    }

public:
    DataVector Prod(const DataVector& v)
    {
        if (v.size() < 2)
        {
            return v;
        }

        DataVector result, left, right;
        InitTables(v, left, right);

        auto l = left.begin();
        auto r = right.begin();
        result.push_back(*r++);
        while (r != right.end())
        {
            ++ops_;
            result.push_back(*l++ * *r++);
        }
        result.push_back(*l++);
        return result;
    }

    auto Ops() const
    {
        return ops_;
    }
};
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.