সরাসরি পর্বে যান
পর্ব ৩৫ · ৮৩-এর মধ্যে · মডিউল ৬

পুনরাবৃত্তিসহ বাছাই — stars and bars আর multinomial

Combinations with Repetition — Stars and Bars, Integer Solutions with Bounds, Permutations of Multisets, the Multinomial Theorem and the Twelvefold Way

Taught in Bangla, this lesson counts selections where types may repeat and order does not matter. It proves C(n + r - 1, r) through the stars and bars bijection, counts integer solutions with lower bounds, inequalities and upper bounds, and proves the multiset permutation count and the multinomial theorem. It lays out the twelvefold way for balls and boxes and marks which cells need later numbers, while in-page Python brute-forces stars and bars, bounded solutions, multinomial coefficients and the twelve cells.

এই পর্বে যা শিখবেন

  • পুনরাবৃত্তিসহ বাছাই কেন আলাদা প্রশ্ন, আর গণনার চারটি মূল মডেল চেনা
  • Stars and bars-এর bijection, আর তা থেকে C(n + r − 1, r)-এর পূর্ণ প্রমাণ
  • নিম্নসীমা, অসমতা আর ঊর্ধ্বসীমাসহ পূর্ণসংখ্যা সমাধান গোনা, আর Python-এ brute force দিয়ে মেলানো
  • Multiset-এর permutation, multinomial coefficient আর multinomial theorem-এর প্রমাণ
  • বল-বাক্স বণ্টনের twelvefold way: কোন ঘর এই পর্বে মেটে, আর কোনগুলো পরের মডিউলে

১ · একই জিনিস বারবার — পুনরাবৃত্তিসহ বাছাই কেন আলাদা

কাল্পনিক অনলাইন দোকান বাজারঘর চার ফ্লেভারের চা বিক্রি করে: আদা, এলাচ, লেবু আর মসলা। একজন ক্রেতা একটি “পছন্দের ঝুড়ি”-তে ৬টি প্যাকেট নেবেন, যেকোনো ফ্লেভার যতবার খুশি। ঝুড়িতে প্যাকেটগুলোর কোনো ক্রম নেই: “২টি আদা, ৩টি লেবু, ১টি মসলা” একটিই ঝুড়ি, কোন প্যাকেট আগে তোলা হয়েছিল তাতে কিছু আসে যায় না। প্রশ্ন: মোট কতগুলো আলাদা ঝুড়ি সম্ভব?

প্রথম চেষ্টায় অনেকে লেখেন 46 = 4096, কারণ প্রতিটি প্যাকেটের ৪টি পছন্দ। কিন্তু এটি গোনে প্যাকেট তোলার ক্রম: “আদা, তারপর লেবু” আর “লেবু, তারপর আদা” আলাদা হিসেবে আসে। তখন মনে হয় ক্রম বাদ দিতে 6! দিয়ে ভাগ করলেই হয়: 4096/720 ≈ 5.69, যা পূর্ণসংখ্যাই নয়! ভুলটি কোথায়, তা §৮-এ বিস্তারিত দেখবেন; আপাতত মনে রাখুন, এখানে একটি নতুন গণনার প্রশ্ন দাঁড়িয়েছে, আর তার জন্য নতুন কৌশল লাগবে।

মিষ্টির দোকানে গিয়ে বলেন, “রসগোল্লা, চমচম আর কালোজাম মিলিয়ে এক কেজিতে ১২টি দিন।” দোকানি জানতে চান না কোন মিষ্টি আগে বাক্সে উঠবে; জানতে চান শুধু কোন মিষ্টি কয়টি। অর্থাৎ বাছাইটি পুরোপুরি ঠিক হয়ে যায় তিনটি সংখ্যা দিয়ে: রসগোল্লা কয়টি, চমচম কয়টি, কালোজাম কয়টি, যাদের যোগফল ১২. এই পর্বের মূল চাবিটি এখানেই: ক্রমহীন, পুনরাবৃত্তিসহ বাছাই মানে আসলে কয়েকটি অঋণাত্মক সংখ্যা, যাদের যোগফল নির্দিষ্ট।

গণনার চারটি মূল মডেল

n ধরনের (বা n-টি আলাদা) জিনিস থেকে r-টি বাছার প্রশ্নে দুটি হ্যাঁ-না প্রশ্ন আছে: ক্রম গুরুত্বপূর্ণ কি না, আর একই জিনিস একাধিকবার নেওয়া যায় কি না। চার সম্ভাবনার তিনটি আপনি আগেই দেখেছেন; চতুর্থটি এই পর্বের বিষয়।

ক্রমপুনরাবৃত্তিসংখ্যাউদাহরণ (n = 3, r = 2: A, B, C)
গুরুত্বপূর্ণচলেnr (গুণের নিয়ম)9: AA AB AC BA BB BC CA CB CC
গুরুত্বপূর্ণচলে নাP(n, r) = n!/(n − r)!6: AB AC BA BC CA CB
গুরুত্বহীনচলে নাC(n, r) = n!/(r!(n − r)!)3: AB AC BC
গুরুত্বহীনচলেC(n + r − 1, r)6: AA AB AC BB BC CC

প্রথম সারি পর্ব ৩১ “গণনার মূল নিয়ম — যোগ, গুণ, বিয়োগ আর ভাগ”-এর গুণের নিয়ম (আর পর্ব ১৬-এ গোনা nrটি ফাংশন), দ্বিতীয় আর তৃতীয় সারি পর্ব ৩৩ “Permutation আর combination”-এর বিষয়। শেষ সারিতে ছোট উদাহরণেই দেখা যায়, উত্তর 6 = C(4, 2), আর 32/2! = 4.5 নয়। কারণ ক্রমসহ তালিকায় AB আর BA দুবার আসে, কিন্তু AA আসে মাত্র একবার; প্রতিটি ক্রমহীন বাছাই একই সংখ্যকবার গোনা হয়নি, তাই একটি সংখ্যা দিয়ে ভাগ করে ঠিক উত্তর আসে না।

সংজ্ঞা ১.১ (পুনরাবৃত্তিসহ r-combination)

n উপাদানের একটি সেট S = {s1, …, sn} থেকে পুনরাবৃত্তিসহ r-combination হলো S-এর উপাদান দিয়ে গড়া r আকারের একটি multiset, অর্থাৎ এমন সংগ্রহ যেখানে একই উপাদান একাধিকবার থাকতে পারে আর ক্রমের কোনো মূল্য নেই। প্রতিটি এমন multiset ঠিক একটি তালিকা (x1, …, xn) দিয়ে চেনা যায়, যেখানে xᵢ হলো sᵢ কতবার আছে, প্রতিটি xᵢ ≥ 0, আর x1 + … + xn = r.

শেষ বাক্যটি নিজেই একটি bijection (পর্ব ১৬): “S থেকে r আকারের multiset” আর “যোগফল r এমন n-টি অঋণাত্মক পূর্ণসংখ্যার তালিকা”, দুটি সেট সমান আকারের। বাজারঘরের ঝুড়িতে তালিকাটি (আদা, এলাচ, লেবু, মসলা) = (2, 0, 3, 1) এর মতো, যোগফল ৬. তাই প্রশ্নটি দাঁড়াল: x1 + x2 + x3 + x4 = 6-এর অঋণাত্মক পূর্ণসংখ্যা সমাধান কয়টি? এর উত্তর দেয় পরের অংশের একটি সুন্দর ছবি।

২ · Stars and bars — একটি ছবি, একটি bijection, একটি সূত্র

ধরুন তিন ফ্লেভারের (আদা, এলাচ, লেবু) ৫টি প্যাকেটের একটি ঝুড়ি: ২টি আদা, ০টি এলাচ, ৩টি লেবু. প্রতিটি প্যাকেটকে একটি তারা ★ দিয়ে আঁকুন, আর ফ্লেভারগুলোর মাঝে দুটি দেয়াল │ বসান: প্রথম দেয়ালের বাঁয়ে আদা, দুই দেয়ালের মাঝে এলাচ, দ্বিতীয় দেয়ালের ডানে লেবু. ঝুড়িটি হয়ে যায় ★★││★★★, সাত চিহ্নের একটি সারি। উল্টো দিকেও কাজ চলে: ★│★★★│★ সারিটি পড়লে পাই ১টি আদা, ৩টি এলাচ, ১টি লেবু. এই কৌশলের নাম stars and bars.

ঝুড়ি থেকে তারা-দেয়ালের সারি

উপরে ৫টি প্যাকেটের একটি ঝুড়ি (x₁, x₂, x₃) = (2, 0, 3); নিচে একই ঝুড়ি ৭টি ঘরের সারিতে, যেখানে লাল দেয়াল বসেছে ৩ আর ৪ নম্বর ঘরে।

Stars and bars: (2, 0, 3) maps to stars-stars-bar-bar-stars-stars-stars; C(7, 2) = 21 ★ ★ (খালি) ★ ★ ★ আদা: x₁ = 2 এলাচ: x₂ = 0 লেবু: x₃ = 3 ★ ★ ★ ★ ★ 1234567 ৭টি ঘরের ২টিতে দেয়াল → C(7, 2) = 21

এখন গোনা সহজ। প্রতিটি সারিতে ঠিক ৭টি ঘর (৫টি তারা আর ২টি দেয়াল), আর সারিটি পুরো ঠিক হয়ে যায় দেয়াল দুটি কোন দুই ঘরে বসল তা দিয়ে। ৭টি ঘর থেকে ২টি বাছার উপায় C(7, 2) = 21 (পর্ব ৩৩-এর সাধারণ binomial coefficient দিয়ে)। তাই তিন ফ্লেভারের ৫ প্যাকেটের ঝুড়ি ২১টি। সাধারণ রূপটি এবার প্রমাণসহ।

উপপাদ্য ২.১ (পুনরাবৃত্তিসহ combination)

n ≥ 1 আর r ≥ 0 পূর্ণসংখ্যা হলে n উপাদানের সেট থেকে পুনরাবৃত্তিসহ r-combination-এর সংখ্যা, অর্থাৎ x1 + x2 + … + xn = r-এর অঋণাত্মক পূর্ণসংখ্যা সমাধানের সংখ্যা

C(n + r − 1, r) = C(n + r − 1, n − 1) = (n + r − 1)! / (r! (n − 1)!)

প্রমাণ (bijection দিয়ে): ধরুন X = {(x1, …, xn) : প্রতিটি xᵢ অঋণাত্মক পূর্ণসংখ্যা, যোগফল r}, আর B = দৈর্ঘ্য n + r − 1-এর এমন সব সারি, যার ঠিক r-টি ঘরে ★ আর n − 1টি ঘরে │.

  1. f: X → B সংজ্ঞায়িত করুন: f(x1, …, xn) = ★x₁ │ ★x₂ │ ⋯ │ ★xₙ, যেখানে ★k মানে পরপর k-টি তারা। এতে তারা আছে x1 + … + xn = r-টি আর দেয়াল n − 1টি, তাই f(x) ∈ B. — f সুসংজ্ঞায়িত
  2. g: B → X সংজ্ঞায়িত করুন: একটি সারির n − 1টি দেয়াল তাকে বাঁ থেকে ডানে n-টি (হয়তো ফাঁকা) খণ্ডে ভাগ করে; i-তম খণ্ডের তারার সংখ্যা yᵢ ধরুন। yᵢ ≥ 0 আর মোট তারা r, তাই g(সারি) = (y1, …, yn) ∈ X. — g সুসংজ্ঞায়িত
  3. g(f(x)) = x, কারণ f(x)-এর i-তম খণ্ডে ঠিক xᵢ-টি তারা বসানো হয়েছিল। আর f(g(s)) = s, কারণ খণ্ডের তারার সংখ্যা আর দেয়ালের অবস্থান মিলে সারিটি হুবহু ফিরে আসে। — দুই দিকেই inverse
  4. যে ফাংশনের দুই দিকের inverse আছে, তা bijection, আর সসীম সেটে bijection মানে |X| = |B|. — পর্ব ১৬
  5. B-এর একটি সারি পুরো ঠিক হয় n + r − 1টি ঘরের কোন n − 1টিতে দেয়াল বসল, তা দিয়ে; তাই |B| = C(n + r − 1, n − 1), আর C(m, k) = C(m, m − k) বলে এটি C(n + r − 1, r)-ও। ∎ — combination-এর সংজ্ঞা

খেয়াল করুন, প্রমাণে কোথাও “ভাগ করে ঠিক করা” নেই: আমরা অচেনা একটি সেটকে চেনা একটি সেটের সঙ্গে এক-এক জোড়ায় মিলিয়েছি। এটিই combinatorial proof-এর একটি রূপ, যা পর্ব ৩৭ “গণনার কৌশল — lattice path, bijection আর double counting”-এ আরও ব্যবহার হবে। বাজারঘরের ৪ ফ্লেভার আর ৬ প্যাকেটে n = 4, r = 6, তাই উত্তর C(9, 6) = C(9, 3) = 84, যা 4096-এর তুলনায় অনেক ছোট। নিচের stepper ছোট উদাহরণ x1 + x2 + x3 = 5-এ প্রমাণের প্রতিটি দিক দেখায়।

1x₁ + x₂ + x₃ = 5, xᵢ ≥ 02(2, 0, 3) → ★★││★★★3★│★★★│★ → (1, 3, 1)4৫ তারা + ২ দেয়াল = ৭ ঘর5C(7, 2) = 216x₁ = 0..5: 6+5+4+3+2+1
চলক
সমাধান
সারি
দেয়ালের ঘর
  1. প্রশ্ন। তিনটি অঋণাত্মক পূর্ণসংখ্যা, যোগফল 5. প্রতিটি সমাধান তিন ফ্লেভারের ৫ প্যাকেটের একটি ঝুড়ি।
  2. f: সমাধান থেকে সারি। (2, 0, 3)-এ দুটি তারা, দেয়াল, শূন্য তারা, দেয়াল, তিনটি তারা: ★★││★★★. দেয়াল বসেছে ৩ আর ৪ নম্বর ঘরে।
  3. g: সারি থেকে সমাধান। ★│★★★│★ সারিতে দেয়াল ২ আর ৬ নম্বর ঘরে; তিন খণ্ডে তারা 1, 3, 1. তাই সমাধান (1, 3, 1), যোগফল 5 ✓.
  4. সারির মাপ। প্রতিটি সারিতে r = 5টি তারা আর n − 1 = 2টি দেয়াল, মোট ৭টি ঘর। সারি চেনা যায় শুধু দেয়ালের ঘর দুটি দিয়ে।
  5. গোনা। ৭টি ঘর থেকে দেয়ালের জন্য ২টি বাছাই: C(7, 2) = 7 · 6 / 2 = 21. f আর g পরস্পরের inverse, তাই সমাধানও ২১টি।
  6. অন্য পথে মেলানো। x₁ = k নিলে বাকি x₂ + x₃ = 5 − k-এর 6 − k-টি সমাধান। k = 0 থেকে 5 পর্যন্ত যোগ: 6 + 5 + 4 + 3 + 2 + 1 = 21 ✓.

Bijection-টি এবার Python-এ দেখা যাক। নিচের ব্লক x1 + x2 + x3 = 5-এর সব সমাধান brute force-এ বের করে, প্রতিটিকে সারিতে রূপান্তর করে (তারার বদলে *, দেয়ালের বদলে |), উল্টো ফাংশন দিয়ে ফেরত আনে, আর শেষে দেখে যে দেয়াল বসানোর সব উপায় ঠিক এই সারিগুলোই। প্রথমবার চালালে ব্রাউজারে Python (Pyodide) নামতে কয়েক সেকেন্ড লাগে।

from itertools import product, combinations
from math import comb

def to_stars(x):                 # (2, 0, 3) -> "**||***"
    return "|".join("*" * xi for xi in x)

def from_stars(s):               # inverse: count the stars between bars
    return tuple(len(part) for part in s.split("|"))

n, r = 3, 5
solutions = [x for x in product(range(r + 1), repeat=n) if sum(x) == r]
strings = [to_stars(x) for x in solutions]
for x, s in list(zip(solutions, strings))[:5]:
    print(x, "->", s)
print("...")
print("solutions:", len(solutions), " distinct strings:", len(set(strings)))
print("inverse gives back every solution:",
      all(from_stars(s) == x for x, s in zip(solutions, strings)))

# other direction: every way to put n-1 bars into n+r-1 places
L = n + r - 1
placements = {"".join("|" if i in bars else "*" for i in range(L))
              for bars in combinations(range(L), n - 1)}
print("bar placements:", len(placements), " C(7, 2) =", comb(L, n - 1))
print("placements == images of solutions:", placements == set(strings))

আসল আউটপুট (ব্রাউজারের Python):

(0, 0, 5) -> ||*****
(0, 1, 4) -> |*|****
(0, 2, 3) -> |**|***
(0, 3, 2) -> |***|**
(0, 4, 1) -> |****|*
...
solutions: 21  distinct strings: 21
inverse gives back every solution: True
bar placements: 21  C(7, 2) = 21
placements == images of solutions: True

প্রথম পাঁচ লাইনে f-এর কাজ দেখা যায়: x1 = 0 হলে সারি শুরু হয় দেয়াল দিয়ে, আর (0, 0, 5)-এ দুটি দেয়াল পাশাপাশি। ২১টি সমাধান থেকে ২১টি আলাদা সারি এসেছে, তাই f one-to-one; উল্টো ফাংশন প্রতিটি সমাধান ফেরত দিয়েছে। শেষ দুই লাইন onto দিকটি দেখায়: ৭টি ঘরে ২টি দেয়াল বসানোর C(7, 2) = 21টি উপায়ের প্রতিটিই কোনো সমাধানের ছবি। প্রমাণের ধাপ ১–৫ এখানে একটি নির্দিষ্ট n, r-এ পরীক্ষিত; প্রমাণটি সব n, r-এ একসঙ্গে বলে।

৩ · পূর্ণসংখ্যা সমাধান — নিম্নসীমা আর অসমতা

বাস্তব প্রশ্নে প্রায়ই শর্ত থাকে। বাজারঘর ঈদের আগে ১০টি একই রকম উপহারের প্যাকেট ৪টি জেলার (ঢাকা, চট্টগ্রাম, রাজশাহী, খুলনা) গুদামে পাঠাবে, আর প্রতিটি জেলা অন্তত একটি পাবে। প্যাকেটগুলো একই রকম, তাই কোন প্যাকেট কোথায় গেল তা নয়, শুধু কোন জেলা কয়টি পেল তা গুরুত্বপূর্ণ: x1 + x2 + x3 + x4 = 10, প্রতিটি xᵢ ≥ 1. কৌশলটি দৈনন্দিন: আগে প্রত্যেক জেলাকে একটি করে প্যাকেট দিয়ে দিন, তারপর বাকিগুলো স্বাধীনভাবে ভাগ করুন।

উপপাদ্য ৩.১ (নিম্নসীমাসহ সমাধান)

a1, …, an অঋণাত্মক পূর্ণসংখ্যা আর A = a1 + … + an ≤ r হলে x1 + … + xn = r, xᵢ ≥ aᵢ-এর পূর্ণসংখ্যা সমাধানের সংখ্যা C(r − A + n − 1, n − 1). A > r হলে কোনো সমাধান নেই। বিশেষ ক্ষেত্র: প্রতিটি xᵢ ≥ 1 হলে (r ≥ n) সংখ্যাটি C(r − 1, n − 1).

প্রমাণ:

  1. φ(x1, …, xn) = (x1 − a1, …, xn − an) নিন। xᵢ ≥ aᵢ বলে প্রতিটি yᵢ = xᵢ − aᵢ ≥ 0, আর ∑yᵢ = r − A. — প্রতিস্থাপন
  2. উল্টো দিকে ψ(y) = (y1 + a1, …, yn + an) যেকোনো অঋণাত্মক সমাধান y-কে মূল সমস্যার একটি সমাধানে নেয়, আর ψ ∘ φ ও φ ∘ ψ দুটিই identity. তাই φ একটি bijection. — পর্ব ১৬
  3. উপপাদ্য ২.১ অনুযায়ী y1 + … + yn = r − A-এর অঋণাত্মক সমাধান C(r − A + n − 1, n − 1)টি। A > r হলে ডান পাশ ঋণাত্মক, আর অঋণাত্মক সংখ্যার যোগফল ঋণাত্মক হতে পারে না। — উপপাদ্য ২.১
  4. সব aᵢ = 1 হলে A = n, আর সংখ্যাটি C(r − n + n − 1, n − 1) = C(r − 1, n − 1). ∎ — বসানো

প্রতিটি xᵢ ≥ 1 এমন সমাধানের জন্য একটি সরাসরি ছবিও আছে: r-টি তারা এক সারিতে রাখুন; তাদের মাঝে r − 1টি ফাঁক। প্রতিটি দেয়াল একটি আলাদা ফাঁকে বসালে কোনো খণ্ড ফাঁকা থাকে না, তাই উত্তর হলো r − 1টি ফাঁক থেকে n − 1টি বাছাই, অর্থাৎ C(r − 1, n − 1). ক্রমসহ এমন যোগফলকে বলে r-এর একটি composition; যেমন 3-এর composition 3, 2 + 1, 1 + 2, 1 + 1 + 1, মোট 4 = 23−1টি (পর্ব ৩৭-এ এর bijective প্রমাণ আসবে)।

1x₁+x₂+x₃+x₄ = 10, xᵢ ≥ 12আগে প্রত্যেককে 1: বাকি 63yᵢ = xᵢ − 1 ≥ 04y₁+y₂+y₃+y₄ = 65৬ তারা + ৩ দেয়াল = ৯ ঘর6C(9, 3) = 84
চলক
উদাহরণ x
উদাহরণ y
যোগফল
  1. মডেল। ঢাকা, চট্টগ্রাম, রাজশাহী, খুলনা পাবে x₁, x₂, x₃, x₄টি; যোগফল 10, প্রত্যেকে অন্তত 1. যেমন (3, 1, 4, 2) একটি বৈধ বণ্টন।
  2. আগে একটি করে। প্রত্যেক জেলায় একটি প্যাকেট আগেই পাঠানো হলো; এতে কোনো পছন্দ নেই, কারণ প্যাকেটগুলো একই রকম। বাকি থাকল 10 − 4 = 6টি।
  3. নতুন চলক। yᵢ = xᵢ − 1 মানে “অতিরিক্ত কয়টি পেল”. (3, 1, 4, 2) হয়ে যায় (2, 0, 3, 1), আর y-এর যোগফল 6, শর্ত শুধু yᵢ ≥ 0.
  4. Stars and bars. ৬টি তারা আর ৩টি দেয়াল, মোট ৯টি ঘর। (2, 0, 3, 1)-এর সারি ★★││★★★│★, দেয়াল ৩, ৪ আর ৮ নম্বর ঘরে।
  5. উত্তর। C(9, 3) = 9 · 8 · 7 / 6 = 84. উপপাদ্য ৩.১-এর সরাসরি সূত্র C(10 − 1, 4 − 1) = C(9, 3)-ও একই কথা বলে।

একটি কৌতূহল খেয়াল করুন: ৪ ফ্লেভার থেকে ৬ প্যাকেটের ঝুড়িও 84টি। কাকতালীয় নয়! নিম্নসীমা সরানোর পর জেলার প্রশ্নটি হুবহু y1 + y2 + y3 + y4 = 6, যা ঝুড়ির প্রশ্নের একই সমীকরণ। দুটি আলাদা গল্প একই গাণিতিক বস্তুতে মিলে গেলে গোনার কাজ অর্ধেক হয়ে যায়।

অসমতা: “বড়জোর r”

ধরুন বাজারঘরের একজন রাইডার দিনে তিনটি এলাকায় বড়জোর ৫টি ডেলিভারি দিতে পারেন: x1 + x2 + x3 ≤ 5, xᵢ ≥ 0. প্রতিটি সম্ভাব্য যোগফল 0, 1, …, 5 আলাদা করে গুনে যোগ করা যায়, কিন্তু একটি ছোট কৌশল আরও সুন্দর। একটি নতুন চলক x4 = 5 − (x1 + x2 + x3) যোগ করুন, যাকে বলে slack variable (“কতটা ক্ষমতা খালি রইল”)। অসমতাটি তখন সমীকরণ x1 + x2 + x3 + x4 = 5, সব xᵢ ≥ 0, আর এই রূপান্তরও একটি bijection. উত্তর C(5 + 4 − 1, 3) = C(8, 3) = 56. সাধারণভাবে x1 + … + xn ≤ r-এর অঋণাত্মক সমাধান C(r + n, n)টি।

এবার সব দাবি brute force-এ মেলানো যাক। নিচের ব্লকের count ফাংশন প্রতিটি চলকের সম্ভাব্য সব মান নিয়ে সব তালিকা পরীক্ষা করে (গুণের নিয়মে কতগুলো, তা শেষ লাইনগুলোয় দেখবেন), আর সূত্রের সঙ্গে তুলনা করে। §৪-এর ঊর্ধ্বসীমার দুটি দাবিও এখানে আগাম পরীক্ষিত।

from itertools import product
from math import comb

def count(n, r, lo=None, hi=None):
    """brute force: tuples (x1..xn) with lo_i <= x_i <= hi_i and sum r"""
    lo = lo or [0] * n
    hi = hi or [r] * n
    ranges = [range(a, b + 1) for a, b in zip(lo, hi)]
    return sum(1 for x in product(*ranges) if sum(x) == r)

print("x1+x2+x3 = 5, all >= 0   :", count(3, 5),
      " formula", comb(5 + 3 - 1, 3 - 1))
print("10 packets, 4 districts>=1:", count(4, 10, lo=[1] * 4),
      " formula", comb(10 - 1, 4 - 1))
print("6 packets, 4 flavours     :", count(4, 6),
      " formula", comb(6 + 4 - 1, 6))
print("x1+x2+x3 <= 5 (slack x4)  :", sum(count(3, r) for r in range(6)),
      " formula", comb(5 + 3, 3))
print("x1+x2+x3 = 7, x1 <= 3     :", count(3, 7, hi=[3, 7, 7]),
      " formula", comb(9, 2) - comb(5, 2))
print("x1+x2+x3 = 10, all <= 4   :", count(3, 10, hi=[4] * 3),
      " formula", comb(12, 2) - 3 * comb(7, 2) + 3 * comb(2, 2))

# where brute force stops: tuples examined vs the answer
for n, r in [(4, 10), (6, 20), (8, 30)]:
    print(f"n={n}, r={r}: brute force checks {(r + 1) ** n:,} tuples,"
          f" answer {comb(n + r - 1, r):,}")

আসল আউটপুট (ব্রাউজারের Python):

x1+x2+x3 = 5, all >= 0   : 21  formula 21
10 packets, 4 districts>=1: 84  formula 84
6 packets, 4 flavours     : 84  formula 84
x1+x2+x3 <= 5 (slack x4)  : 56  formula 56
x1+x2+x3 = 7, x1 <= 3     : 26  formula 26
x1+x2+x3 = 10, all <= 4   : 6  formula 6
n=4, r=10: brute force checks 14,641 tuples, answer 286
n=6, r=20: brute force checks 85,766,121 tuples, answer 53,130
n=8, r=30: brute force checks 852,891,037,441 tuples, answer 10,295,472

প্রথম ছয়টি লাইনে প্রতিটি brute-force গণনা সূত্রের সঙ্গে হুবহু মিলেছে: stars and bars (21), নিম্নসীমা (84), ঝুড়ি (84), slack variable (56), আর §৪-এর দুটি ঊর্ধ্বসীমার হিসাব (26 আর 6). শেষ তিন লাইন শুধু ছাপায়, চালায় না: brute force প্রতিটি চলকের r + 1টি মান নিয়ে (r + 1)nটি তালিকা দেখে। n = 8, r = 30-এ তা আট লাখ কোটির বেশি, অথচ উত্তর মাত্র এক কোটির মতো, আর সূত্রে তা এক মুহূর্তে আসে। ছোট ক্ষেত্রে brute force সূত্রকে যাচাই করে; বড় ক্ষেত্রে সূত্রই একমাত্র উপায়।

৪ · ঊর্ধ্বসীমা — খারাপগুলো বাদ দেওয়ার হিসাব

নিম্নসীমা সহজে সরে যায়, কিন্তু ঊর্ধ্বসীমা (xᵢ ≤ uᵢ) প্রতিস্থাপনে সরে না। ধরুন গুদামে আদা চা আছে মাত্র ৩ প্যাকেট, আর একজন ক্রেতা তিন ফ্লেভার মিলিয়ে ৭ প্যাকেট নেবেন: x1 + x2 + x3 = 7, 0 ≤ x1 ≤ 3. কৌশল: পর্ব ৩১-এর complement বা বিয়োগের নিয়ম। আগে শর্ত ছাড়া সব গুনুন, তারপর “খারাপ” সমাধান, অর্থাৎ x1 ≥ 4, বাদ দিন।

  1. শর্ত ছাড়া: C(7 + 2, 2) = C(9, 2) = 36.
  2. খারাপ (x1 ≥ 4): y1 = x1 − 4 বসালে y1 + x2 + x3 = 3, তাই C(5, 2) = 10. খারাপ সমাধানের নিম্নসীমা আছে, আর নিম্নসীমা আমরা জানি সরাতে।
  3. ভালো = 36 − 10 = 26 (Python-এর পঞ্চম লাইন)।

একাধিক ঊর্ধ্বসীমা থাকলে সাবধান হতে হয়। x1 + x2 + x3 = 10, প্রতিটি xᵢ ≤ 4 প্রশ্নে খারাপ সমাধান মানে কোনো একটি xᵢ ≥ 5. ধরুন Aᵢ = “xᵢ ≥ 5” এমন সমাধানের সেট।

  1. শর্ত ছাড়া: C(12, 2) = 66. প্রতিটি |Aᵢ|: xᵢ থেকে 5 সরালে যোগফল 5, তাই C(7, 2) = 21; তিনটি মিলে 63.
  2. কিন্তু 66 − 63 = 3 ভুল উত্তর, কারণ যে সমাধানে দুটি চলকই ≥ 5, যেমন (5, 5, 0), তা A1 আর A2 দুই সেটেই আছে আর দুবার বাদ পড়েছে। |Aᵢ ∩ Aⱼ|: দুটি থেকে 5 করে সরালে যোগফল 0, তাই C(2, 2) = 1টি; তিনটি জোড়ায় 3, যা ফেরত যোগ করতে হবে।
  3. তিনটিই ≥ 5 হলে যোগফল অন্তত 15 > 10, তাই A1 ∩ A2 ∩ A3 ফাঁকা।
  4. উত্তর 66 − 63 + 3 − 0 = 6. তালিকা দিয়ে মেলানো যায়: (4, 4, 2) আর (4, 3, 3)-এর প্রতিটির ৩টি করে বিন্যাস, মোট 6 ✓.

এই “যোগ, বিয়োগ, আবার যোগ” হলো inclusion–exclusion-এর নীতি। দুই সেটের রূপ |A ∪ B| = |A| + |B| − |A ∩ B| আপনি পর্ব ১৫-এ দেখেছেন; যেকোনো সংখ্যক সেটের পূর্ণ রূপ আর তার প্রমাণ আসবে পর্ব ৪৯ “Inclusion–exclusion আর derangement”-এ। আপাতত সূত্রের ধাঁচটি মনে রাখুন: x1 + … + xn = r, সব xᵢ ≤ u হলে উত্তর ∑j ≥ 0 (−1)j C(n, j) C(r − j(u + 1) + n − 1, n − 1), যেখানে r − j(u + 1) ঋণাত্মক হলে সেই পদ বাদ। যাচাই: ৪ ফ্লেভার থেকে ৬ প্যাকেট, প্রতি ফ্লেভারে বড়জোর ২টি হলে C(9, 3) − 4 · C(6, 3) + 6 · C(3, 3) = 84 − 80 + 6 = 10, আর scratch-এ brute force-ও 10 দিয়েছে।

সাধারণ ভুল: ঊর্ধ্বসীমাকে নিম্নসীমার মতো প্রতিস্থাপনে সরানোর চেষ্টা। y = 4 − x1 বসালে নতুন চলক অঋণাত্মক হয় ঠিকই, কিন্তু যোগফলের সমীকরণে −y আসে, আর stars and bars আর খাটে না। আরেকটি ভুল: একাধিক শর্তে শুধু একবার বিয়োগ করা, যেমন ওপরের 66 − 63 = 3. ছোট উদাহরণে brute force দিয়ে মেলালেই এমন ভুল ধরা পড়ে।

৫ · Multiset সারিতে সাজানো — একই জিনিসের permutation

এ পর্যন্ত আমরা ক্রমহীন বাছাই গুনেছি। এবার উল্টো প্রশ্ন: জিনিসগুলো ঠিক করা, কিন্তু ক্রম গুরুত্বপূর্ণ, আর কিছু জিনিস হুবহু একই রকম। বাজারঘরের দোকানের একটি তাকে পাশাপাশি ৯টি পণ্য সাজাতে হবে: ২টি একই রকম চায়ের প্যাকেট (T), ৩টি একই রকম সাবান (S), ৪টি একই রকম বিস্কুটের প্যাকেট (B). তাকের চেহারা কতভাবে আলাদা হতে পারে? দুটি চায়ের প্যাকেট অদলবদল করলে তাক দেখতে একই থাকে, তাই 9! = 362880 অনেক বেশি গোনে।

পর্ব ৩৩-এ পুনরাবৃত্ত অক্ষরসহ শব্দ সাজানোর উদাহরণ দেখেছেন। এখানে তার সাধারণ উপপাদ্য আর দুটি প্রমাণ। ধরুন n-টি জিনিস m ধরনের, i-তম ধরনের kᵢ-টি একই রকম, k1 + … + km = n. এমন সংগ্রহের একটি সারিকে বলে multiset-এর permutation.

উপপাদ্য ৫.১ (multiset-এর permutation)

উপরের শর্তে আলাদা আলাদা সারির সংখ্যা

n! / (k1! k2! ⋯ km!)

প্রমাণ ১ (ভাগের নিয়ম):

  1. সাময়িকভাবে একই রকম জিনিসগুলোর গায়ে লেবেল লাগান (T1, T2, S1, …), যাতে n-টিই আলাদা হয়। তখন সারি n!টি। — permutation, পর্ব ৩৩
  2. লেবেলসহ একটি সারি থেকে লেবেল মুছলে লেবেলহীন একটি সারি পাওয়া যায়। লেবেলহীন একটি নির্দিষ্ট সারি থেকে লেবেলসহ সারি বানাতে i-তম ধরনের kᵢ-টি জায়গায় তার লেবেলগুলো যেকোনো ক্রমে বসানো যায়: kᵢ! উপায়, আর সব ধরন মিলিয়ে গুণের নিয়মে k1!⋯km! উপায়। — গুণের নিয়ম
  3. অর্থাৎ “লেবেল মোছা” ফাংশনটি প্রতিটি লেবেলহীন সারির ওপর ঠিক k1!⋯km!টি সারিকে পাঠায়। প্রতিটি ছবির ঠিক একই সংখ্যক পূর্বরূপ আছে বলে ভাগ বৈধ: লেবেলহীন সারি = n!/(k1!⋯km!). ∎ — ভাগের নিয়ম, পর্ব ৩১

প্রমাণ ২ (জায়গা বাছাই): n-টি জায়গার কোন k1টিতে প্রথম ধরন বসবে, তা C(n, k1) উপায়ে; বাকি n − k1টি জায়গা থেকে দ্বিতীয় ধরনের জন্য C(n − k1, k2) উপায়ে; এভাবে চলতে থাকে। গুণের নিয়মে মোট C(n, k1) · C(n − k1, k2) ⋯ C(km, km). প্রতিটি C-কে factorial-এ লিখলে পরপর হর-লব কেটে যায় (telescoping), আর থাকে n!/(k1!⋯km!). ∎

প্রমাণ ১-এর ধাপ ৩ খুব গুরুত্বপূর্ণ, কারণ এখানেই §১-এর 46/6! ভুলের উত্তর লুকিয়ে আছে। ভাগের নিয়ম খাটে কেবল তখন, যখন প্রতিটি “ফলাফল” ঠিক একই সংখ্যকবার গোনা হয়েছে। তাকের প্রশ্নে তা সত্য, কারণ প্রতিটি লেবেলহীন সারির ঠিক 2! · 3! · 4! = 288টি লেবেলসহ রূপ। ঝুড়ির প্রশ্নে তা মিথ্যা: “৬টিই আদা” ঝুড়িটি ক্রমসহ তালিকায় মাত্র একবার আসে, কিন্তু “আদা, এলাচ, লেবু, মসলা, আদা, এলাচ”-এর মতো ঝুড়ি আসে 6!/(2!2!) = 180 বার। নিচের stepper তাকের হিসাব ধাপে ধাপে দেখায়।

1সব আলাদা ধরলে: 9! = 3628802÷ 2! (দুটি চা)3÷ 3! (তিনটি সাবান)4÷ 4! (চারটি বিস্কুট)5C(9,2)·C(7,3)·C(4,4)
চলক
এখনকার মান
উদাহরণ সারি
  1. লেবেল লাগানো। চা T₁, T₂, সাবান S₁–S₃, বিস্কুট B₁–B₄; সব আলাদা হলে 9! = 362880টি সারি। কিন্তু তাকে লেবেল দেখা যায় না।
  2. চায়ের লেবেল মোছা। T₁ আর T₂ অদলবদল করলে একই চেহারা, তাই প্রতিটি চেহারা ২ বার গোনা ছিল: 362880 / 2 = 181440.
  3. সাবানের লেবেল মোছা। তিনটি সাবানের 3! = 6টি ক্রম একই চেহারা দেয়: 181440 / 6 = 30240.
  4. বিস্কুটের লেবেল মোছা। চারটি বিস্কুটের 4! = 24টি ক্রম একই চেহারা: 30240 / 24 = 1260. এটিই আলাদা তাকের সংখ্যা।
  5. জায়গা বাছাই করে মেলানো। ৯টি ঘর থেকে চায়ের ২টি C(9, 2) = 36, বাকি ৭টি থেকে সাবানের ৩টি C(7, 3) = 35, শেষ ৪টি বিস্কুটের: 36 · 35 · 1 = 1260 ✓.

একটি বাংলা নামের উদাহরণ: “BAZARGHAR” (বাজারঘর-এর ইংরেজি বানান) শব্দের ৯টি অক্ষরে A আছে ৩টি, R ২টি, আর B, Z, G, H একটি করে। তাই আলাদা বিন্যাস 9!/(3! · 2!) = 30240. যেসব ধরনের kᵢ = 1, তাদের 1! = 1 দিয়ে ভাগে কিছু বদলায় না।

৬ · Multinomial coefficient আর multinomial theorem

সংজ্ঞা ৬.১ (multinomial coefficient)

k1, …, km অঋণাত্মক পূর্ণসংখ্যা আর k1 + … + km = n হলে

C(n; k1, k2, …, km) = n! / (k1! k2! ⋯ km!)

এটি multinomial coefficient. m = 2 হলে C(n; k, n − k) = C(n, k), অর্থাৎ binomial coefficient এর বিশেষ ক্ষেত্র।

উপপাদ্য ৫.১ থেকেই এর তিনটি সমতুল্য অর্থ আসে: (ক) k1টি প্রথম ধরন, k2টি দ্বিতীয় ধরন ইত্যাদির সারি; (খ) n-টি আলাদা জিনিসকে লেবেল দেওয়া m-টি দলে ভাগ, যাতে i-তম দলে ঠিক kᵢ-টি থাকে (যেমন ৯ জন রাইডারকে ঢাকা, চট্টগ্রাম, খুলনা দলে 2, 3, 4 জন করে পাঠানো: 1260 উপায়); (গ) অক্ষর বসানো শব্দ। (খ) আর (ক) একই, কারণ রাইডারদের নির্দিষ্ট ক্রমে দাঁড় করালে প্রত্যেকের গায়ে তাঁর দলের নাম একটি “অক্ষর”.

উপপাদ্য ৬.২ (multinomial theorem)

n ≥ 0 পূর্ণসংখ্যা আর x1, …, xm যেকোনো সংখ্যা (বা পরস্পর বিনিময়যোগ্য চলক) হলে

(x1 + x2 + … + xm)n = ∑ C(n; k1, …, km) · x1k₁ x2k₂ ⋯ xmkₘ

যেখানে যোগফলটি চলে k1 + … + km = n এমন সব অঋণাত্মক পূর্ণসংখ্যার তালিকার ওপর।

প্রমাণ:

  1. (x1 + … + xm)n হলো n-টি একই বন্ধনীর গুণফল। বন্টন নিয়মে (distributive law) পুরো গুণ খুললে প্রতিটি পদ আসে প্রতিটি বন্ধনী থেকে একটি করে চলক বেছে গুণ করে; বাছাইগুলোকে দৈর্ঘ্য n-এর একটি শব্দ হিসেবে লেখা যায়, যার অক্ষর x1, …, xm. তাই খোলা রূপে ঠিক mnটি পদ। — বন্টন নিয়ম, গুণের নিয়ম
  2. একটি শব্দের গুণফল x1k₁⋯xmkₘ হয় ঠিক তখন, যখন শব্দে x1 আছে k1 বার, …, xm আছে km বার, কারণ চলকগুলো বিনিময়যোগ্য। — গুণের বিনিময় ধর্ম
  3. এমন শব্দের সংখ্যা উপপাদ্য ৫.১ অনুযায়ী n!/(k1!⋯km!). তাই একই পদগুলো একত্র করলে x1k₁⋯xmkₘ-এর সহগ C(n; k1, …, km). ∎ — উপপাদ্য ৫.১

এই প্রমাণ থেকে তিনটি বিনামূল্যের ফল আসে। প্রথমত, সব xi = 1 বসালে ∑ C(n; k1, …, km) = mn: দৈর্ঘ্য n-এর সব শব্দ, অক্ষরের গণনা অনুযায়ী দলে ভাগ করা। দ্বিতীয়ত, আলাদা আলাদা পদ (monomial) কয়টি? প্রতিটি পদ একটি তালিকা (k1, …, km), যোগফল n, তাই stars and bars অনুযায়ী C(n + m − 1, m − 1)টি। এখানে এই পর্বের দুই অংশ একসঙ্গে মিলল। তৃতীয়ত, m = 2 হলে এটিই পর্ব ৩৪ “Binomial coefficient, Pascal-এর ত্রিভুজ আর combinatorial identity”-এর binomial theorem. যেমন (x + y + z)6-এ x2y3z-এর সহগ 6!/(2! 3! 1!) = 60, আর মোট পদ C(8, 2) = 28. নিচের ব্লক এসব দাবি সরাসরি গুণ খুলে মেলায়।

from itertools import product, permutations
from collections import Counter
from math import factorial, prod

def multinomial(*ks):            # (k1+...+km)! / (k1! ... km!)
    return factorial(sum(ks)) // prod(factorial(k) for k in ks)

# 1) shelf: 2 tea (T), 3 soap (S), 4 biscuit (B)
shelf = "TTSSSBBBB"
orders = set(permutations(shelf))          # 9! = 362880 orders, many equal
print("distinct shelf orders:", len(orders), " formula:", multinomial(2, 3, 4))

# 2) expand (x+y+z)^4 by brute force: one letter from each bracket
terms = Counter("".join(sorted(w)) for w in product("xyz", repeat=4))
ok = all(c == multinomial(m.count("x"), m.count("y"), m.count("z"))
         for m, c in terms.items())
print("(x+y+z)^4:", len(terms), "monomials, all match multinomial:", ok)
print("coefficient of x^2*y*z:", terms["xxyz"],
      " sum of coefficients:", sum(terms.values()), "= 3^4")

# 3) (x+y+z)^6: coefficient of x^2 y^3 z
c6 = Counter("".join(sorted(w)) for w in product("xyz", repeat=6))
print("x^2*y^3*z in (x+y+z)^6:", c6["xxyyyz"], " formula:", multinomial(2, 3, 1))
print("monomials in (x+y+z)^6:", len(c6), " = C(8, 2)")

আসল আউটপুট (ব্রাউজারের Python):

distinct shelf orders: 1260  formula: 1260
(x+y+z)^4: 15 monomials, all match multinomial: True
coefficient of x^2*y*z: 12  sum of coefficients: 81 = 3^4
x^2*y^3*z in (x+y+z)^6: 60  formula: 60
monomials in (x+y+z)^6: 28  = C(8, 2)

প্রথম লাইনে Python 9! = 362880টি সারি বানিয়ে সেট দিয়ে একই রকমগুলো মিলিয়ে দিয়েছে: ঠিক 1260টি আলাদা তাক, stepper-এর উত্তর। দ্বিতীয় অংশটি প্রমাণের ধাপ ১ হুবহু অনুসরণ করে: প্রতিটি বন্ধনী থেকে একটি অক্ষর বেছে 34 = 81টি শব্দ, তারপর অক্ষর সাজিয়ে একই পদ এক করা। ১৫টি পদ (C(6, 2) = 15) পাওয়া গেছে, প্রতিটির সহগ সূত্রের সঙ্গে মিলেছে, যেমন x2yz-এর 4!/(2!1!1!) = 12, আর সহগের যোগফল 81. শেষ দুই লাইনে (x + y + z)6-এর দাবি দুটি, 60 আর 28, নিশ্চিত হলো। এটি প্রমাণ নয়, কিন্তু ভুল সূত্র থাকলে এমন পরীক্ষায় সঙ্গে সঙ্গে ধরা পড়ত।

ইতিহাস: Multinomial theorem-এর ধারণা Gottfried Wilhelm Leibniz ১৬৯০-এর দশকে Johann Bernoulli-কে লেখা চিঠিতে আলোচনা করেছিলেন, আর প্রথম প্রকাশিত প্রমাণ Abraham de Moivre-এর ১৬৯৭ সালের একটি প্রবন্ধে, এমনটিই সাধারণত উল্লেখ করা হয়; সঠিক সাল আর কৃতিত্ব নিয়ে উৎসভেদে কিছু পার্থক্য আছে। পুনরাবৃত্তিসহ বাছাইয়ের সূত্রটি এর চেয়েও পুরোনো সমস্যা থেকে আসে, যেমন কয়েকটি পাশা ছুড়লে কতগুলো আলাদা “ফল” (ক্রম বাদ দিয়ে) সম্ভব; আর “stars and bars” নামটি William Feller-এর ১৯৫০ সালের সম্ভাবনার পাঠ্যবইয়ের মাধ্যমে জনপ্রিয় হয়েছে বলে প্রায়ই বলা হয়।

৭ · বল আর বাক্স — বণ্টনের বারো পথ

এই মডিউলের প্রায় সব গণনাকে একটি ভাষায় লেখা যায়: n-টি বল k-টি বাক্সে রাখার উপায় কয়টি? তিনটি প্রশ্নের উত্তর আগে ঠিক করতে হয়। বলগুলো কি আলাদা (রাইডারের নাম, পার্সেল নম্বর), না একই রকম (উপহারের প্যাকেট, টাকা)? বাক্সগুলো কি আলাদা (জেলা, ফ্লেভার), না একই রকম (নামহীন একই মাপের ব্যাগ, শুধু দলে ভাগ)? আর শর্ত কী: যেকোনোভাবে, প্রতি বাক্সে বড়জোর একটি (injection), নাকি প্রতি বাক্সে অন্তত একটি (surjection)? ২ × ২ × ৩ = ১২টি সম্ভাবনা, যার নাম twelvefold way. আলাদা বল আর আলাদা বাক্সের ক্ষেত্রে বণ্টন আসলে একটি ফাংশন f: বল → বাক্স; বাকি ক্ষেত্রগুলো সেই ফাংশনের কিছু তথ্য “ভুলে যাওয়া”.

n বল → k বাক্সযেকোনোভাবেপ্রতি বাক্সে বড়জোর ১টিপ্রতি বাক্সে অন্তত ১টি
আলাদা বল, আলাদা বাক্সkn (পর্ব ১৬, ৩১)P(k, n) = k!/(k − n)! (পর্ব ৩৩)k! · S(n, k) (পর্ব ৪৯, ৫০)
একই রকম বল, আলাদা বাক্সC(n + k − 1, n) (§২)C(k, n)C(n − 1, k − 1) (§৩)
আলাদা বল, একই রকম বাক্সS(n, 1) + … + S(n, k) (পর্ব ৫০)n ≤ k হলে 1, নইলে 0S(n, k) (পর্ব ৫০)
একই রকম বল, একই রকম বাক্সn-এর বড়জোর k অংশে partition (পর্ব ৫০)n ≤ k হলে 1, নইলে 0n-এর ঠিক k অংশে partition (পর্ব ৫০)

গাঢ় করা তিনটি ঘর এই পর্বের। মাঝের ঘরটি C(k, n) কেন? একই রকম বল, প্রতি বাক্সে বড়জোর একটি: বণ্টন ঠিক হয় শুধু কোন n-টি বাক্সে বল পড়ল তা দিয়ে, অর্থাৎ k-টি বাক্স থেকে n-টির একটি সাধারণ বাছাই। প্রথম সারির surjection-এর সংখ্যা inclusion–exclusion দিয়ে বের হয় (পর্ব ৪৯), আর সেখানে আসে S(n, k), যাকে বলে দ্বিতীয় ধরনের Stirling সংখ্যা: n-টি আলাদা জিনিসকে k-টি নামহীন, অশূন্য দলে ভাগ করার উপায়। নিচের দুই সারির জন্য S(n, k) আর পূর্ণসংখ্যার partition, যার কোনো সহজ closed form নেই; এরা পর্ব ৫০ “বিশেষ সংখ্যা — Catalan, Stirling আর partition”-এর বিষয়। এখানে আমরা শুধু ছোট উদাহরণে সব ১২টি ঘর brute force-এ গুনে দেখব।

from itertools import product
from math import comb

n, k = 4, 3                                  # 4 balls, 3 boxes
maps = list(product(range(k), repeat=n))     # ball i goes to box f[i]

def sizes(f):                                # balls in box 0, 1, 2
    return tuple(f.count(b) for b in range(k))

def grouping(f):                             # which balls share a box
    blocks = {frozenset(i for i in range(n) if f[i] == b) for b in range(k)}
    return frozenset(blocks - {frozenset()})

def row(name, objects, size_list):
    total = len(objects)
    at_most_1 = sum(1 for o in objects if max(size_list(o)) <= 1)
    at_least_1 = sum(1 for o in objects if min(size_list(o)) >= 1)
    print(f"{name:<22}{total:>5}{at_most_1:>6}{at_least_1:>6}")

print(f"{'balls / boxes':<22}{'any':>5}{'<=1':>6}{'>=1':>6}")
row("distinct / distinct", maps, sizes)
row("identical / distinct", {sizes(f) for f in maps}, lambda s: s)
row("distinct / identical", {grouping(f) for f in maps},
    lambda g: [len(b) for b in g] + [0] * (k - len(g)))
row("identical / identical", {tuple(sorted(sizes(f))) for f in maps},
    lambda s: s)
print("formulas: k^n =", k ** n, " C(n+k-1, n) =", comb(n + k - 1, n),
      " C(n-1, k-1) =", comb(n - 1, k - 1))

আসল আউটপুট (ব্রাউজারের Python):

balls / boxes           any   <=1   >=1
distinct / distinct      81     0    36
identical / distinct     15     0     3
distinct / identical     14     0     6
identical / identical     4     0     1
formulas: k^n = 81  C(n+k-1, n) = 15  C(n-1, k-1) = 3

কৌশলটি হলো “ভুলে যাওয়া”: প্রথমে 34 = 81টি ফাংশন বানানো হয়েছে; বল একই রকম হলে শুধু প্রতিটি বাক্সের বলের সংখ্যা রাখা হয়েছে (15 = C(6, 4), stars and bars); বাক্স একই রকম হলে শুধু কোন বলগুলো একসঙ্গে আছে তা (14 = 1 + 7 + 6); আর দুটোই একই রকম হলে শুধু সাজানো সংখ্যাগুলো: 4, 3 + 1, 2 + 2, 2 + 1 + 1, মোট ৪টি partition. “বড়জোর ১টি” কলামটি পুরো শূন্য, কারণ ৪টি বল ৩টি বাক্সে রাখলে কোনো বাক্সে অন্তত দুটি পড়বেই, যা পর্ব ৩২ “Pigeonhole principle — সহজ থেকে generalized”-এর নীতি (pigeonhole principle অনুযায়ী)। শেষ কলামে 36 = 3! · S(4, 3) = 6 · 6, আর তৃতীয় সারির 6 নিজেই S(4, 3). সারণির সূত্রগুলো এভাবে ছোট উদাহরণে মিলিয়ে নিলে পর্ব ৪৯ আর ৫০-এর জন্য আগাম ভিত তৈরি হয়।

সম্ভাবনায় সাবধান: stars and bars গোনে আলাদা ফলাফল, কিন্তু সেই ফলাফলগুলো সমান সম্ভাব্য হয় না। দুটি পাশা ছুড়লে ক্রমহীন ফল ২১টি (C(7, 2)), কিন্তু {1, 1}-এর সম্ভাবনা 1/36 আর {1, 2}-এর 2/36, কারণ বাস্তবের পাশা দুটি আলাদা বস্তু। সম্ভাবনায় “সমান সম্ভাব্য” sample space বেছে নেওয়ার বিষয়টি পর্ব ৩৮ “বিচ্ছিন্ন সম্ভাবনা — sample space, event আর Laplace-এর সংজ্ঞা”-এ আসবে; AI-এর দৃষ্টিকোণ থেকে সংক্ষিপ্ত রূপ AI Foundations কোর্সের পর্ব ৩৫-এ আছে।

৮ · পরীক্ষার অঙ্ক আর গণনার একটি ভুল প্রমাণ

বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর লিখিত পরীক্ষায় এই পর্বের যে ধাঁচের অঙ্ক আসে, তার কয়েকটি পূর্ণ সমাধান। প্রতিটি সংখ্যা scratch-এ Python দিয়ে brute force-এ মেলানো।

অঙ্ক ১: একটি ক্রিকেট ইনিংসে ১০টি উইকেট

ধরে নিন উইকেট পড়ার ধরন শুধু পাঁচটি: bowled, caught, lbw, run out, stumped (বাস্তবে আরও বিরল কিছু ধরন আছে, এখানে বাদ)। একটি ইনিংসে ১০টি উইকেট পড়লে “কোন ধরনে কয়টি” এর কয়টি আলাদা সারসংক্ষেপ সম্ভব?

  1. কোন উইকেট আগে পড়ল তা সারসংক্ষেপে নেই, আর একই ধরন বারবার আসতে পারে: ৫ ধরন থেকে পুনরাবৃত্তিসহ ১০টির বাছাই।
  2. n = 5, r = 10: C(10 + 5 − 1, 10) = C(14, 4) = 14 · 13 · 12 · 11 / 24 = 1001.

অঙ্ক ২: 0 থেকে 9999-এর মধ্যে অঙ্কের যোগফল 10 এমন সংখ্যা কয়টি?

  1. প্রতিটি সংখ্যাকে চার অঙ্কে লিখুন (যেমন 0046): d1 + d2 + d3 + d4 = 10, প্রতিটি 0 ≤ dᵢ ≤ 9. শর্ত ছাড়া C(13, 3) = 286.
  2. খারাপ: কোনো dᵢ ≥ 10. তখন বাকি তিনটির যোগফল 0, অর্থাৎ সংখ্যাটি দাঁড়ায় একটি অঙ্কে 10 আর বাকি তিনটিতে 0: প্রতিটি i-এর জন্য ঠিক ১টি, মোট ৪টি। দুটি অঙ্ক একসঙ্গে ≥ 10 অসম্ভব।
  3. উত্তর 286 − 4 = 282. (যোগফল 9 হলে কোনো অঙ্ক 9-এর বেশি হতেই পারে না, তাই সরাসরি C(12, 3) = 220.)

অঙ্ক ৩: (a + b + c + d)8-এ a2b3c3-এর সহগ, আর মোট পদের সংখ্যা

  1. d-এর ঘাত 0, আর 2 + 3 + 3 + 0 = 8 ✓. সহগ 8!/(2! 3! 3! 0!) = 40320/72 = 560.
  2. মোট পদ: চারটি অঋণাত্মক ঘাতের যোগফল 8, তাই C(8 + 3, 3) = C(11, 3) = 165.

প্রমাণের ভুল ধরুন: “ক্রম বাদ দিতে r! দিয়ে ভাগ”

একজন লিখলেন: “দাবি: n ধরন থেকে পুনরাবৃত্তিসহ r-টির ক্রমহীন বাছাই nr/r!টি। প্রমাণ: ক্রমসহ বাছাই গুণের নিয়মে nrটি। প্রতিটি ক্রমহীন বাছাইয়ের r-টি জিনিস r! ভাবে সাজানো যায়, তাই প্রতিটি ক্রমহীন বাছাই r! বার গোনা হয়েছে। ভাগের নিয়মে উত্তর nr/r!. ∎” পড়ে ভুলটি নিজে খুঁজুন।

ভুল কোথায়: “r! ভাবে সাজানো যায়” বাক্যটি শুধু তখন সত্য, যখন r-টি জিনিস সব আলাদা। পুনরাবৃত্তি থাকলে একই রকম জিনিস অদলবদল করলে নতুন ক্রম আসে না: {আদা, আদা, লেবু}-এর ক্রম মাত্র 3!/2! = 3টি, 6টি নয়, আর {আদা, আদা, আদা}-এর মাত্র 1টি। ভাগের নিয়মের শর্ত, “প্রতিটি ফলাফল ঠিক একই সংখ্যকবার গোনা”, এখানে ভাঙে। Counterexample: n = 3, r = 2-এ সূত্রটি 9/2 = 4.5 দেয়, যা পূর্ণসংখ্যাই নয়, অথচ আসল উত্তর 6. ঠিক পথ হলো stars and bars-এর bijection, যেখানে কোনো ভাগই লাগে না। এই একই ভুল বাস্তবে ঘটে যখন কেউ “ক্রম বাদ দিতে sort করে unique রাখি, তারপর গুনি” কোডের বদলে মাথায় ভাগ করে নেন।

আরও গভীরে: Stars and bars-এর সংখ্যা C(n + r − 1, r)-কে প্রায়ই “multichoose” বলা হয় আর ((n r)) লেখা হয়; এর generating function হলো 1/(1 − x)n, যার xr-এর সহগ ঠিক এই সংখ্যা, আর ঊর্ধ্বসীমা u থাকলে (1 + x + … + xu)n-এর সহগ, যা §৪-এর inclusion–exclusion সূত্রকে বীজগণিতে ফিরিয়ে দেয় (পর্ব ৪৮ “Generating function — গণনাকে বীজগণিতে রূপান্তর”)। ভিন্ন ওজনের সমীকরণ, যেমন 2x + 5y + 10z = n (খুচরো টাকার প্রশ্ন), stars and bars-এ মেটে না; সেখানে generating function বা DSA কোর্সের পর্ব ৫৩-এর coin change DP লাগে। পূর্ণসংখ্যার partition-সংখ্যা p(n)-এর কোনো সহজ সূত্র নেই, কিন্তু Hardy আর Ramanujan ১৯১৮ সালে এর একটি অসাধারণ নির্ভুল asymptotic সূত্র দেন।

পরীক্ষা ও ইন্টারভিউতে: বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর পরীক্ষায় এই ধরনের প্রশ্ন প্রায়ই আসে:

  • x1 + x2 + x3 = 10-এর অঋণাত্মক সমাধান কয়টি? C(12, 2) = 66; ধনাত্মক হলে C(9, 2) = 36.
  • ৫ ধরনের মিষ্টি থেকে ১২টি নেওয়ার উপায়? C(16, 4) = 1820.
  • “MISSISSIPPI” কতভাবে সাজানো যায়? 11!/(1! 4! 4! 2!) = 34650.
  • (x + y + z)10-এ কয়টি আলাদা পদ? C(12, 2) = 66.
  • ১০টি একই রকম চকলেট ৪ জনকে, প্রত্যেকে অন্তত ২টি? y = x − 2, যোগফল 2: C(5, 3) = 10.

৯ · AI-এর যুগে — গণনার উত্তর যাচাই

গণনার প্রশ্নে AI সহকারী প্রায়ই আত্মবিশ্বাসের সঙ্গে একটি সুন্দর সূত্র বসিয়ে দেয়, আর ভুলটি থাকে মডেল বাছাইয়ে: বল আলাদা না একই রকম, ক্রম আছে কি না, সীমা আছে কি না। এই পর্বের বিষয়ে কয়েকটি ভুল নিয়মিত দেখা যায়:

AI-এর ভুলকীভাবে ধরবেন
nr/r! বা C(n, r) বসিয়ে দেওয়া, যেখানে পুনরাবৃত্তি চলেn = 3, r = 2-এর মতো ছোট উদাহরণে সব বাছাই হাতে বা combinations_with_replacement দিয়ে লিখে গুনুন
Stars and bars-এ off-by-one: n − 1-এর বদলে n-টি দেয়াল, বা C(n + r, r)দেয়াল কয়টি লাগে নিজে আঁকুন; r = 0 বা n = 1-এ উত্তর 1 আসে কি না দেখুন
নিম্নসীমা ভুলে যাওয়া, বা ঊর্ধ্বসীমায় শুধু একবার বিয়োগপ্রতিটি শর্ত আলাদা লিখতে বলুন; brute force দিয়ে মেলান
আলাদা বস্তুকে একই রকম ধরা (রাইডার, পার্সেল) বা উল্টোটা“দুটি অদলবদল করলে কি নতুন ফল?” প্রশ্নটি নিজে জিজ্ঞেস করুন
Stars and bars-এর ফলাফলকে সমান সম্ভাব্য ধরে সম্ভাবনা হিসাবPython-এ seed দিয়ে simulation চালিয়ে ঘনত্ব মেলান
বানানো ইতিহাস বা উৎস, যেমন ভুল সাল বা অস্তিত্বহীন বইবিশ্বস্ত পাঠ্যবই বা মূল উৎসে মিলিয়ে নিন

AI-এর কাছে গণনার সমাধান চাইলে এমন কাঠামো দিন, যাতে মডেল বাছাই আর প্রতিটি ধাপ আলাদা করে পরীক্ষা করা যায়:

নিচের গণনার প্রশ্নটি ধাপে ধাপে সমাধান করো: প্রশ্ন: [যেমন ১০টি একই রকম প্যাকেট ৪টি জেলায়, প্রত্যেকে অন্তত ১টি] ১. প্রথমে মডেল লেখো: বস্তুগুলো আলাদা না একই রকম, বাক্স বা ধরন আলাদা না একই রকম, ক্রম গুরুত্বপূর্ণ কি না, পুনরাবৃত্তি চলে কি না, আর প্রতিটি সীমা (নিম্ন ও ঊর্ধ্ব)। ২. প্রশ্নটিকে একটি সমীকরণ বা সেটে রূপান্তর করো, আর রূপান্তরটি কেন bijection, তা এক লাইনে বলো। ৩. যে সূত্র ব্যবহার করছ (stars and bars, multinomial, inclusion–exclusion), তার পূর্ণ বিবৃতি আর শর্ত লেখো; কোনো ধাপে ভাগ করলে দেখাও প্রতিটি ফল ঠিক একই সংখ্যকবার গোনা হয়েছে। ৪. সংখ্যাগুলো ছোট করে (যেমন ৪টি প্যাকেট, ২টি জেলা) সব ফলাফল তালিকা করে উত্তর মেলাও। ৫. শেষে brute force দিয়ে যাচাইয়ের একটি ছোট Python কোড দাও (itertools আর math.comb ব্যবহার করে)।

AI-এর উত্তর হাতে পেলে — যাচাইয়ের চেকলিস্ট

গণনার প্রায় প্রতিটি দাবি ছোট সংখ্যায় এক সেকেন্ডে brute force করা যায়। AI যত সুন্দর সূত্রই দিক, আগে n = 3, r = 4-এর মতো ছোট ক্ষেত্রে সব ফল তালিকা করে মেলান; সূত্র ভুল হলে প্রায় সবসময় সেখানেই ধরা পড়ে।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন, তারপর “→ উত্তর” চাপুন।

প্র ০১সত্যেন্দ্রনাথ বসু ১৯২৪ সালে ঢাকায় বসে আলোর কণা গোনার যে নতুন পদ্ধতি দেন, তার সঙ্গে stars and bars-এর সম্পর্ক কী? twelvefold way-এর সারণিতে পদার্থবিজ্ঞানের তিনটি পরিসংখ্যান কোথায় বসে?

সত্যেন্দ্রনাথ বসু তখন ঢাকা বিশ্ববিদ্যালয়ের পদার্থবিজ্ঞান বিভাগে পড়াতেন। ১৯২৪ সালে তিনি Planck-এর বিকিরণ সূত্রের একটি নতুন উৎপাদন লিখে Albert Einstein-কে পাঠান; Einstein লেখাটি জার্মান ভাষায় অনুবাদ করে Zeitschrift für Physik পত্রিকায় প্রকাশের ব্যবস্থা করেন, আর পরে একই ধারণা পরমাণুর গ্যাসে প্রসারিত করেন। এখান থেকেই Bose–Einstein পরিসংখ্যান, আর পরে Paul Dirac-এর দেওয়া নাম “boson”. বিবরণের খুঁটিনাটি নিয়ে উৎসভেদে পার্থক্য আছে, কিন্তু মূল ঘটনাক্রম সুপ্রতিষ্ঠিত।

গণিতের দিক থেকে মূল পরিবর্তনটি ছিল গোনার মডেলে। পুরোনো Maxwell–Boltzmann পদ্ধতিতে কণাগুলো আলাদা ধরা হতো: r-টি কণাকে n-টি শক্তি-ঘরে রাখার উপায় nr, অর্থাৎ সারণির “আলাদা বল, আলাদা বাক্স, যেকোনোভাবে”. বসুর পদ্ধতিতে কণাগুলো অভিন্ন: শুধু কোন ঘরে কয়টি কণা, সেটিই একটি অবস্থা। তখন অবস্থার সংখ্যা C(n + r − 1, r), হুবহু stars and bars, সারণির “একই রকম বল, আলাদা বাক্স”. ১৯২৬ সালে Enrico Fermi আর Dirac আরেক ধরনের কণার জন্য পরিসংখ্যান দেন, যেখানে Pauli-র বর্জন নীতি অনুযায়ী এক ঘরে বড়জোর একটি কণা থাকতে পারে: অবস্থার সংখ্যা C(n, r), সারণির “একই রকম বল, প্রতি বাক্সে বড়জোর একটি”. ছোট উদাহরণ: ২টি কণা, ৩টি ঘর হলে তিন মডেলে যথাক্রমে 9, 6 আর 3টি অবস্থা।

শিক্ষাটি গভীর: কোনটি “আলাদা” আর কোনটি “একই রকম”, তা গণিতের প্রশ্ন নয়, প্রকৃতি বা সমস্যার মডেলের প্রশ্ন। ভুল মডেল বেছে নিলে নির্ভুল হিসাবও ভুল পূর্বাভাস দেয়। আর প্রতিটি অবস্থাকে সমান সম্ভাব্য ধরা হবে কোন স্তরে, সেটিও মডেলের অংশ; বসুর সাফল্য দেখিয়েছিল আলোর কণার জন্য ঠিক স্তরটি কোনটি। বাংলাদেশের এক শ্রেণিকক্ষ থেকে আসা এই ধারণা আজ লেজার, অতিশীতল পরমাণুর Bose–Einstein condensate আর কণা-পদার্থবিজ্ঞানের ভিত্তির অংশ।

মূল উপলব্ধি: একই ঘটনাকে কোন গণনার মডেলে দেখা হবে, সেই সিদ্ধান্তই আসল বিজ্ঞান; stars and bars শুধু “অভিন্ন বস্তু” মডেলের নির্ভুল হিসাব।

প্র ০২দুটি পাশা ছুড়লে ক্রমহীন ফল ২১টি। তাহলে “দুটিই ছক্কা” পাওয়ার সম্ভাবনা কি 1/21? গণনা আর সম্ভাবনার এই বিভ্রান্তির ইতিহাস কী, আর কীভাবে এড়াবেন?

না, সম্ভাবনা 1/36. ক্রমহীন ফল {6, 6} আসে ক্রমসহ মাত্র একটি পথে (6, 6), কিন্তু {5, 6} আসে দুটি পথে, (5, 6) আর (6, 5). আসল পাশা দুটি আলাদা বস্তু, ভিন্ন জায়গায় পড়ে, তাই ৩৬টি ক্রমসহ ফলই সমান সম্ভাব্য; ২১টি ক্রমহীন ফল সমান সম্ভাব্য নয়। stars and bars সঠিকভাবে বলে কতগুলো আলাদা ফলাফল সম্ভব, কিন্তু বলে না তারা কত ঘন ঘন ঘটে।

এই বিভ্রান্তি পুরোনো। ফরাসি গণিতবিদ Jean le Rond d'Alembert ১৭৫০-এর দশকে Encyclopédie-র একটি নিবন্ধে দুবার মুদ্রা ছোড়ায় অন্তত একবার head পাওয়ার সম্ভাবনা 2/3 বলে যুক্তি দেন বলে উল্লেখ করা হয়: তাঁর মতে ফল তিনটি, “প্রথমবারেই head”, “tail তারপর head”, আর “দুবারই tail”, আর তিনটিকে তিনি সমান সম্ভাব্য ধরেন। সঠিক উত্তর 3/4, কারণ প্রথম ফলটি আসলে দুটি সমান সম্ভাব্য ফলের মিলন। আরও আগে Galileo-কে তিন পাশার যোগফল 9 আর 10-এর তুলনা নিয়ে প্রশ্ন করা হয়েছিল বলে প্রচলিত: দুটি যোগফলেরই ছয়টি ক্রমহীন রূপ, কিন্তু ক্রমসহ গুনলে 25 আর 27, আর জুয়াড়িরা অভিজ্ঞতায় পার্থক্য টের পেয়েছিলেন।

এড়ানোর উপায় তিনটি। এক, sample space হিসেবে সবসময় সবচেয়ে “সূক্ষ্ম” বর্ণনা নিন, যেখানে প্রতিটি বস্তু আলাদা, আর সেখানে সমান সম্ভাবনা যুক্তিসংগত কি না ভাবুন। দুই, ক্রমহীন ফলের সম্ভাবনা চাইলে প্রতিটির ক্রমসহ রূপ গুনুন, যা multinomial coefficient দেয়: তিন পাশায় {2, 3, 4}-এর 3! = 6টি রূপ, {3, 3, 3}-এর 1টি। তিন, সন্দেহ হলে seed-সহ simulation চালান; কয়েক লাখ ছোড়ায় 1/21 আর 1/36-এর পার্থক্য স্পষ্ট দেখা যায়। বসুর গল্প (প্র ০১) দেখায়, প্রকৃতিতে কখনো কখনো ক্রমহীন অবস্থাই সমান সম্ভাব্য; তাই এটি গণিতের নিয়ম নয়, মডেলের সিদ্ধান্ত। সম্ভাবনার পূর্ণ আলোচনা পর্ব ৩৮-এ আসবে।

মূল উপলব্ধি: গণনা বলে কতগুলো ফল, সম্ভাবনা বলে কত ঘন ঘন; দুটির মাঝে সেতু হলো “কোন ফলগুলো সমান সম্ভাব্য” এই মডেলের সিদ্ধান্ত, যা সবসময় স্পষ্ট করে লিখতে হয়।

প্র ০৩“Twelvefold way” নামে বণ্টনের প্রশ্নগুলো একটি সারণিতে সাজানোর ধারণা কোথা থেকে এল, আর সারণির কিছু ঘরের সহজ সূত্র নেই কেন?

গণনার প্রশ্ন সাজানোর এই পদ্ধতি সাধারণত Gian-Carlo Rota-র কাজের সঙ্গে যুক্ত বলে উল্লেখ করা হয়, আর Richard Stanley-র ১৯৮৬ সালের বই “Enumerative Combinatorics” (প্রথম খণ্ড)-এর মাধ্যমে তা ব্যাপক পরিচিতি পায়; Stanley-র বইয়ে নামটির কৃতিত্ব Joel Spencer-কে দেওয়া হয়েছে বলে উল্লেখিত। মূল ভাবনাটি হলো, সব বণ্টন আসলে একটি ফাংশন f: N → K (বল থেকে বাক্স), আর তিনটি প্রশ্ন: f-এর ওপর কোনো শর্ত আছে কি না (যেকোনো, injective, surjective), আর বলের বা বাক্সের নাম মুছে দিলে কোন ফাংশনগুলোকে একই ধরা হবে। এক কথায়, একটি সারণি “ফাংশন গোনা” আর “সমতুল্যতা” (পর্ব ৫৫-এর equivalence relation)-কে একসঙ্গে দেখায়।

সারণির ওপরের দুই সারির সব ঘরে সহজ সূত্র আছে, কারণ বাক্সগুলো আলাদা: প্রতিটি বাক্সকে নাম ধরে আলাদাভাবে ভাবা যায়, আর গুণের নিয়ম আর stars and bars যথেষ্ট। বাক্স একই রকম হলেই সমস্যা কঠিন হয়, কারণ তখন “কোন দল কোন বাক্সে” তথ্যটি নেই, আর একই দলগঠনকে অনেকবার গুনে ফেলা সহজ। আলাদা বলের জন্য উত্তর দাঁড়ায় দ্বিতীয় ধরনের Stirling সংখ্যা, যার একটি recurrence আর inclusion–exclusion সূত্র আছে, কিন্তু factorial-এর মতো সরল গুণফল নেই। একই রকম বল আর একই রকম বাক্সে উত্তর partition সংখ্যা p(n), যার কোনো সরল closed form জানা নেই: p(100) = 190569292, যা scratch-এ recurrence দিয়ে মেলানো।

Partition-এর ইতিহাস বাংলা পাঠকের জন্য আকর্ষণীয়: Srinivasa Ramanujan আর G. H. Hardy ১৯১৮ সালে p(n)-এর জন্য একটি asymptotic সূত্র দেন, যা থেকে অবিশ্বাস্য রকম নির্ভুল মান পাওয়া যায়, আর Ramanujan p(n)-এর কিছু বিস্ময়কর বিভাজ্যতাও আবিষ্কার করেন, যেমন p(5k + 4) সবসময় 5 দিয়ে বিভাজ্য। এসব পর্ব ৫০-এ আসবে। কম্পিউটার বিজ্ঞানে সারণিটি একটি চিন্তার চেকলিস্ট: load balancing-এ সার্ভার আলাদা কি না, clustering-এ দলের নাম আছে কি না, এই প্রশ্নগুলো সঠিক সূত্রের দিকে নিয়ে যায়।

মূল উপলব্ধি: বণ্টনের প্রায় সব প্রশ্ন তিনটি সিদ্ধান্তে ১২টি ঘরের একটিতে পড়ে; বাক্স আলাদা হলে সূত্র সহজ, বাক্স অভিন্ন হলে সমতুল্যতার কারণে সমস্যা কঠিন হয়ে ওঠে।

প্র ০৪Multinomial coefficient কম্পিউটার বিজ্ঞান আর ডেটার কাজে কোথায় আসে, আর বড় সংখ্যায় একে নিরাপদে হিসাব করবেন কীভাবে?

প্রথম প্রয়োগ শব্দ আর ক্রম গোনা। একটি DNA খণ্ডে A, C, G, T-এর সংখ্যা জানা থাকলে সেই গঠনের কতগুলো আলাদা ক্রম সম্ভব, তা multinomial coefficient. প্রতিটি অক্ষর-গঠনের জন্য এত বিশাল সংখ্যক ক্রম থাকে বলেই শুধু গঠন দেখে ক্রম অনুমান করা যায় না। পাসওয়ার্ড নীতিতেও একই কথা: “ঠিক ২টি অঙ্ক, ১টি চিহ্ন, ৫টি অক্ষর” শর্তের জায়গা বাছাই একটি multinomial, তারপর প্রতিটি জায়গার পছন্দ গুণের নিয়মে।

দ্বিতীয় প্রয়োগ সম্ভাবনা আর মেশিন লার্নিং। n-টি স্বাধীন পরীক্ষার প্রতিটিতে m-টি ফলের একটি আসে, সম্ভাবনা p1, …, pm; তাহলে ঠিক k1, …, km বার আসার সম্ভাবনা C(n; k1, …, km) p1k₁⋯pmkₘ. এটি multinomial distribution, multinomial theorem থেকেই যার সম্ভাবনাগুলোর যোগফল (p1 + … + pm)n = 1. লেখাকে “শব্দের থলি” (bag of words) হিসেবে দেখার মডেল এর ওপর দাঁড়িয়ে, যেমন AI Foundations কোর্সের পর্ব ৫১-এর spam ফিল্টার। সেখানে শব্দের ক্রম ফেলে দিয়ে শুধু কোন শব্দ কয়বার, সেটিই রাখা হয়: ঠিক এই পর্বের “ক্রমহীন, পুনরাবৃত্তিসহ” মডেল।

হিসাবের দিক: n! খুব দ্রুত বড় হয়; 20! প্রায় 2.4 × 1018, যা 64-bit পূর্ণসংখ্যার সীমার কাছাকাছি, আর 21! তা ছাড়িয়ে যায়। তাই C বা Java-য় আগে n! হিসাব করে পরে ভাগ করলে overflow হয়, যদিও উত্তরটি ছোট হতে পারে। নিরাপদ পথ হলো প্রমাণ ২-এর সূত্র: C(n, k1) · C(n − k1, k2) ⋯, আর প্রতিটি binomial-কে এমনভাবে হিসাব করা যাতে প্রতিটি মধ্যবর্তী ভাগ পূর্ণসংখ্যা থাকে। Python-এর int যেকোনো আকারের, তাই সেখানে এই সমস্যা নেই। প্রোগ্রামিং প্রতিযোগিতায় সাধারণত উত্তর একটি মৌলিক সংখ্যা p (যেমন 109 + 7) দিয়ে mod নিয়ে চাওয়া হয়; তখন factorial আগে থেকে হিসাব করে রাখা হয় আর ভাগের বদলে Fermat-এর ছোট উপপাদ্য দিয়ে modular inverse নেওয়া হয় (পর্ব ২৪, আর কোডের জন্য DSA কোর্সের পর্ব ৬২), যার শর্ত হলো n < p.

মূল উপলব্ধি: Multinomial coefficient একই সঙ্গে ক্রম গোনে, সম্ভাবনা দেয় আর বড় সংখ্যায় সাবধানী হিসাব দাবি করে; কোন রূপে লিখবেন, তা নির্ভর করে আপনার যন্ত্রের সংখ্যার সীমার ওপর।

প্র ০৫Stars and bars কখন কাজ করে না? খুচরো টাকা গোনা বা ওজনযুক্ত সমীকরণে কোন পদ্ধতি লাগে, আর সূত্র বনাম algorithm-এর এই সীমারেখা কী শেখায়?

Stars and bars-এর মূল শর্ত হলো প্রতিটি চলকের সহগ 1: প্রতিটি তারা যেকোনো খণ্ডে গেলে মোট একই পরিমাণ যোগ করে। বাজারঘরের ক্যাশে 2, 5 আর 10 টাকার নোট দিয়ে 50 টাকা দেওয়ার উপায় গুনতে হলে সমীকরণ 2x + 5y + 10z = 50; এখানে একটি “তারা” কোন খণ্ডে গেল তার ওপর যোগফল নির্ভর করে, তাই দেয়াল বসানোর সরল ছবি ভেঙে যায়। কয়েকটি বিশেষ ক্ষেত্রে চলক ধরে ধরে যোগ করে সূত্র পাওয়া যায়, কিন্তু সাধারণভাবে কোনো সরল closed form নেই।

এখানে দুটি শক্তিশালী পদ্ধতি আছে। প্রথমটি generating function: (1 + t2 + t4 + …)(1 + t5 + t10 + …)(1 + t10 + …)-এর t50-এর সহগই উত্তর, আর গুণফলকে বীজগণিতে নাড়াচাড়া করে অনেক কিছু প্রমাণ করা যায় (পর্ব ৪৮)। দ্বিতীয়টি dynamic programming: ways[s] = s টাকা বানানোর উপায়, আর প্রতিটি নোটের জন্য টেবিলটি একবার হালনাগাদ করা, যা DSA কোর্সের পর্ব ৫৩-এর coin change সমস্যা। আসলে DP টেবিলটি generating function-এর গুণফলকে সংখ্যায় হিসাব করার একটি উপায়; দুটি একই গণিতের দুই রূপ।

ঊর্ধ্বসীমাও এই সীমারেখার কাছে নিয়ে যায়: কয়েকটি সীমা থাকলে inclusion–exclusion সুন্দর সূত্র দেয়, কিন্তু প্রতিটি চলকের আলাদা সীমা আর অনেক চলক থাকলে পদের সংখ্যা 2n-এর মতো বাড়ে, আর তখন DP বেশি ব্যবহারিক। শিক্ষাটি হলো: closed form সবচেয়ে ভালো, কারণ তা প্রমাণ দেয়, বড় মানে তাৎক্ষণিক উত্তর দেয়, আর কাঠামো বোঝায়। কিন্তু সূত্র না থাকলে হাল ছাড়ার কিছু নেই; একটি সঠিক recurrence আর তার কার্যকর algorithm-ও পূর্ণ সমাধান। আর উভয় ক্ষেত্রেই ছোট মানে brute force দিয়ে মেলানো সবচেয়ে সস্তা বিমা।

মূল উপলব্ধি: Stars and bars একক ওজনের, সীমাহীন বা নিম্নসীমার সমীকরণের নিখুঁত হাতিয়ার; ওজন বা অনেক ঊর্ধ্বসীমা এলে generating function আর DP তার স্বাভাবিক উত্তরসূরি।

অনুশীলন

আগে খাতায় করুন, তারপর উত্তর খুলে মেলান।

  1. প্রমাণ: n ≥ 2 আর r ≥ 0 হলে প্রমাণ করুন, C(n + r − 1, r) = ∑j=0r C(n + j − 2, j). (ইঙ্গিত: x1 + … + xn = r-এর সমাধানগুলোকে xn-এর মান অনুযায়ী ভাগ করুন।)
    1. বাঁ পাশ উপপাদ্য ২.১ অনুযায়ী x1 + … + xn = r-এর অঋণাত্মক সমাধানের সংখ্যা। — stars and bars
    2. প্রতিটি সমাধানে xn = r − j, যেখানে j ∈ {0, 1, …, r} ঠিক একটি মান। তাই সমাধানের সেটটি r + 1টি পরস্পর বিচ্ছিন্ন অংশে ভাগ হয়। — যোগের নিয়ম
    3. j নির্দিষ্ট হলে বাকি x1 + … + xn−1 = j, n − 1টি চলক, তাই C(j + (n − 1) − 1, j) = C(n + j − 2, j)টি সমাধান। — উপপাদ্য ২.১
    4. সব অংশ যোগ করলে ডান পাশ। ∎

    এটি আসলে পর্ব ৩৪-এর hockey-stick identity-র একটি রূপ। যাচাই: n = 3, r = 5-এ ডান পাশ 1 + 2 + 3 + 4 + 5 + 6 = 21 = C(7, 5) ✓; scratch-এ 2 ≤ n ≤ 7, 0 ≤ r ≤ 7-এর সব ক্ষেত্রে মেলানো।

  2. হিসাব: (ক) x1 + x2 + x3 + x4 = 15, যেখানে x1 ≥ 2, x2 ≥ 0, x3 ≥ 1, x4 ≥ 3: পূর্ণসংখ্যা সমাধান কয়টি? (খ) ৫টি আলাদা পার্সেল ৩ জন আলাদা রাইডারকে দিতে হবে, প্রত্যেকে অন্তত একটি পাবেন: উপায় কয়টি? (গ) একই প্রশ্নে পার্সেলগুলো একই রকম হলে?

    (ক) নিম্নসীমার যোগফল A = 2 + 0 + 1 + 3 = 6. বাকি 15 − 6 = 9, চারটি অঋণাত্মক চলকে: C(9 + 3, 3) = C(12, 3) = 220.

    (খ) আলাদা বল, আলাদা বাক্স, surjection. সব বণ্টন 35 = 243; কোনো একজন রাইডার খালি হাতে: 3 · 25 = 96; দুজন খালি হাতে: 3 · 15 = 3. Inclusion–exclusion-এ 243 − 96 + 3 = 150 = 3! · S(5, 3) = 6 · 25.

    (গ) একই রকম বল, আলাদা বাক্স, প্রত্যেকে অন্তত একটি: C(5 − 1, 3 − 1) = C(4, 2) = 6. (খ) আর (গ)-এর পার্থক্যই দেখায় “আলাদা না একই রকম” প্রশ্নটি কত বড়। সব সংখ্যা scratch-এ brute force দিয়ে যাচাই করা।

  3. আউটপুট অনুমান: কোড না চালিয়ে বলুন কী ছাপা হবে। তারপর যেকোনো Python-এ চালিয়ে মেলান।
    from itertools import combinations_with_replacement as cwr
    from math import comb
    picks = list(cwr("ABC", 2))
    print(len(picks), comb(3 + 2 - 1, 2))
    print(["".join(p) for p in picks])
    print(len(list(cwr(range(4), 6))))
    6 6
    ['AA', 'AB', 'AC', 'BB', 'BC', 'CC']
    84

    combinations_with_replacement ঠিক পুনরাবৃত্তিসহ, ক্রমহীন বাছাইগুলো দেয়, প্রতিটি একবার, ইনপুটের ক্রম মেনে (তাই BA নেই, শুধু AB আছে)। n = 3, r = 2-এ সংখ্যাটি C(4, 2) = 6. শেষ লাইন বাজারঘরের ঝুড়ির প্রশ্ন: ৪ ফ্লেভার থেকে ৬টি, C(9, 6) = 84.

  4. প্রমাণের ভুল ধরুন: ১০টি একই রকম উপহারের প্যাকেট ৪টি জেলায়, প্রত্যেকে অন্তত একটি। একজন লিখলেন: “প্রথমে প্রত্যেক জেলাকে একটি দিই, এতে 1 উপায়। বাকি ৬টি প্যাকেটের প্রতিটির ৪টি জেলার যেকোনোটিতে যাওয়ার পছন্দ, তাই গুণের নিয়মে 46 = 4096. আরেকভাবে যাচাই: ১০টি তারা আর ৪টি দেয়াল সাজালে C(14, 4) = 1001; দুটি পদ্ধতি আলাদা উত্তর দিলেও প্রথমটি নিশ্চয়ই ঠিক।” কোথায় কোথায় ভুল?
    • ভুল ১: 46 প্যাকেটগুলোকে আলাদা ধরে: “প্যাকেট ১ ঢাকায়, প্যাকেট ২ খুলনায়” আর উল্টোটা আলাদা গোনা হয়েছে, অথচ প্যাকেট একই রকম, শুধু কোন জেলা কয়টি পেল সেটি গুরুত্বপূর্ণ। এটি §১-এর ক্রমসহ গণনার ভুল।
    • ভুল ২: ৪টি জেলাকে আলাদা করতে দেয়াল লাগে 4 − 1 = 3টি, 4টি নয়। আর “অন্তত একটি” শর্ত দ্বিতীয় হিসাবে ব্যবহারই হয়নি।
    • সঠিক হিসাব: প্রত্যেককে একটি দেওয়ার পর বাকি 6, চারটি অঋণাত্মক চলকে: C(6 + 3, 3) = C(9, 3) = 84 (stepper ২ আর Python ব্লকে যাচাই করা)।
    • যুক্তির ভুল: দুটি পদ্ধতি আলাদা উত্তর দিলে “প্রথমটি নিশ্চয়ই ঠিক” বলা যায় না; অন্তত একটি ভুল, আর ছোট উদাহরণে (যেমন ৩টি প্যাকেট, ২টি জেলা: সঠিক উত্তর 2) brute force চালালেই ধরা পড়ে।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমনিম্নসীমাসহ একটি বণ্টনের প্রশ্ন সমাধানের ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. প্রশ্নটিকে x1 + … + xn = r সমীকরণে লেখা
  2. প্রতিটি চলকের নিম্নসীমা aᵢ চিহ্নিত করা
  3. yᵢ = xᵢ − aᵢ বসিয়ে সব নিম্নসীমা 0 করা
  4. নতুন যোগফল r − (a1 + … + an) বের করা
  5. Stars and bars দিয়ে C(নতুন যোগফল + n − 1, n − 1) হিসাব করা
  6. ছোট সংখ্যায় brute force চালিয়ে উত্তর মেলানো

৩ ধরনের ফল থেকে ৫টি ফল নিতে হবে; একই ধরন বারবার নেওয়া যায়, আর ক্রমের কোনো মূল্য নেই। কতগুলো আলাদা বাছাই সম্ভব?

  • 243
  • 21
  • 35
  • 10

x1 + x2 + x3 + x4 = 8 সমীকরণের এমন পূর্ণসংখ্যা সমাধান কয়টি, যেখানে প্রতিটি xᵢ ≥ 1?

  • 165
  • 70
  • 35
  • 56

A, A, B, B, B, C, C, এই ৭টি অক্ষর দিয়ে কতগুলো আলাদা শব্দ (সব অক্ষর ব্যবহার করে) সাজানো যায়?

  • 210
  • 5040
  • 420
  • 35

(x + y + z)6 খুললে x2y3z-এর সহগ কত?

  • 1
  • 20
  • 120
  • 60

(a + b + c + d)5 খুলে একই পদ একত্র করলে কতগুলো আলাদা পদ (monomial) থাকে?

  • 1024
  • 56
  • 126
  • 5

৫টি আলাদা পার্সেল ৩ জন আলাদা রাইডারকে দিতে হবে, প্রত্যেকে অন্তত একটি পাবেন। উপায় কয়টি?

  • 6
  • 243
  • 150
  • 25

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন, অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. Stars and bars: n ধরন থেকে পুনরাবৃত্তিসহ, ক্রমহীন r-টি = x1 + … + xn = r-এর অঋণাত্মক সমাধান = C(n + r − 1, r). প্রমাণ একটি bijection, কোনো ভাগ নেই।
  2. সীমা: xᵢ ≥ 1 হলে C(r − 1, n − 1); xᵢ ≥ aᵢ হলে y = x − a বসান; “≤ r” হলে slack variable; ঊর্ধ্বসীমা complement আর inclusion–exclusion দিয়ে।
  3. Multiset সাজানো: n!/(k1!⋯km!), ভাগের নিয়মে বা জায়গা বাছাইয়ে প্রমাণ। ভাগ বৈধ শুধু যখন প্রতিটি ফল সমান সংখ্যকবার গোনা।
  4. Multinomial theorem: (x1 + … + xm)n-এ x1k₁⋯xmkₘ-এর সহগ n!/(k1!⋯km!); আলাদা পদ C(n + m − 1, m − 1)টি, সহগের যোগফল mn.
  5. বল আর বাক্স: আলাদা না একই রকম (বল আর বাক্স দুটোরই), আর কোনো শর্ত আছে কি না, এই তিন প্রশ্ন আগে; একই রকম বাক্সে Stirling আর partition লাগে (পর্ব ৫০)।

পরের পর্বে: পর্ব ৩৬ “Permutation আর combination তৈরি — lexicographic order আর backtracking”: এ পর্যন্ত আমরা শুধু গুনেছি; এবার সব subset, permutation আর combination একে একে তৈরি করার algorithm, Gray code আর সমান সম্ভাবনায় এলোমেলো permutation বানানোর কৌশল।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান