Number Theory লেবেলটি সহ পোস্টগুলি দেখানো হচ্ছে৷ সকল পোস্ট দেখান
Number Theory লেবেলটি সহ পোস্টগুলি দেখানো হচ্ছে৷ সকল পোস্ট দেখান

বুধবার, ৯ মার্চ, ২০২২

LCM (Least Common Multiple)

একটি সংখ্যা x কে অপর একটি সংখ্যা y দিয়ে ভাগ করলে যদি ভাগশেষ 0 থাকে, তবে x হবে y এর একটি গুণিতক (multiple). যেমন, 24 সংখ্যাটি 6 দিয়ে নিঃশেষে বিভাজ্য, তাই 6 এর একটি গুণিতক হবে 24. 


এখন দুটি সংখ্যা a ও b এর সাধারণ গুণিতক (common multiple) হবে এমন একটি সংখ্যা যেটি a ও b উভয় দিয়েই নিঃশেষে বিভাজ্য। যেমন, 24 সংখ্যাটি 6 ও 8 উভয় দিয়েই নিঃশেষে বিভাজ্য, 6 ও 8 এর একটি সাধারণ গুণিতক হবে 24.


এবার আমরা ধারণা করতেই পারছি যে, লঘিষ্ঠ সাধারণ গুণিতক (Least Common Multiple) হবে সংখ্যা দুটির সাধারণ গুণিতক গুলোর মধ্যে সবচেয়ে ছোট সংখ্যাটি। যেমন, 6 ও 8 এর গুণিতক গুলো হলো 24, 48, 72, 96 ইত্যাদি। এর মধ্যে সবচেয়ে ছোট গুণিতকটি হলো 24. তাই 6 ও 8 এর LCM (Least Common Multiple) হলো 24.


তাহলে আমরা শিখলাম LCM কী জিনিস। এবার আমরা শিখবো দুটি সংখ্যা a ও b এর LCM কিভাবে বের করতে হয়। LCM বের করার দুটি পদ্ধতি দেখবো আমরা। 


পদ্ধতি ১

প্রথমে আমরা a ও b উভয়ের prime factorization বের করবো। এখন কোনো prime factor p এর জন্য a ও b এর উভয়ের prime factorization এ p এর power যেখানে সর্বোচ্চ সেটিকে আমরা LCM এর prime factorization এ রাখবো। যেমন, 


6 এর prime factorization, 6 = 2 x 3

8 এর prime factorization, 8 = 2^3


তাহলে, এদের LCM এ 2 এর power হবে max (1,3) বা 3. আবার LCM এ 3 এর power হবে max(1,0) বা 1.


অতএব, 6 ও 8 এর LCM = 2^3 x 3 = 24.



পদ্ধতি ২

এই পদ্ধতি গতে দুটি সংখ্যার GCD ও LCM এর মধ্যকার সম্পর্কের উপর ভিত্তি করে আমরা তাদের LCM বের করবো। দুটি সংখ্যার গুণফল, তাদের GCD ও LCM এর গুণফলের সমান। অর্থাৎ দুটি সংখ্যা a ও b এর জন্য, 

a x b = GCD(a,b) x LCM(a,b).

তাহলে আমরা লিখতে পারি,

LCM(a,b) =(a x b) / GCD(a,b)

এখন আমরা যদি a ও b এর GCD জানি, তাহলে খুব সহজেই তাদের LCM বের করতে পারবো। 



উপরের দুটি পদ্ধতির মধ্যে প্রথমটিতে আমাদেরকে প্রদত্ত সংখ্যা দুটির prime factorization বের করতে হচ্ছে, যা খুবই time expensive. অন্যদিকে দ্বিতীয় পদ্ধতিতে GCD বের করলেই কাজ হয়ে যাচ্ছে। Prime factorization বের করার তুলনায় GCD বের করার time complexity খুবই কম। তাই আমরা program এ LCM বের করার প্রয়োজন হলে দ্বিতীয় পদ্ধতি অবলম্বন করবো। 

a ও b এর LCM বের করার code

//LCM(a,b) returns the LCM of a and b.


int LCM (int a, int b){

     

     int gcd = __gcd(a,b);      //GCD of a and b

     

     int lcm = (a*b) / gcd;

     

     return lcm;

}




এখন আমাদেরকে যদি তিনটি সংখ্যা a,b ও c এর LCM বের করতে বলা হয়, তাহলে? এর জন্য আমরা প্রথমে a ও b এর LCM বের করব, এরপর তার সাথে c এর LCM বের করলেই সেটি হবে a, b ও c এর LCM. ঠিক একইভাবে আমরা n সংখ্যক integer জন্য LCM বের করতে পারি। 


তাহলে আমরা শিখে ফেললাম কিভাবে দুই বা ততোধিক সংখ্যার LCM বের করতে হয়। এবার আমরা একটু মাথা খাটিয়েই BEE 2514 ও BEE 1909 সমস্যা দুটির সমাধান করে ফেলতে পারি, তাই না?


BEE 2514

Problem link: https://www.beecrowd.com.br/judge/en/problems/view/2514


BEE 1909

Problem link: https://www.beecrowd.com.br/judge/en/problems/view/1909


মঙ্গলবার, ২৩ ফেব্রুয়ারি, ২০২১

Prime Number Checking

 আমরা জানি ১ থেকে বড় যে সকল সংখ্যার ১ এবং ওই সংখ্যা ছাড়া অন্য কোনো উৎপাদক (divisor) নেই তাদেরকে মৌলিক সংখ্যা বলে । এক্ষেত্রে একটি বিষয় লক্ষণীয় যে ১ মৌলিক সংখ্যা নয়। 


এখন যদি বলা কোনো একটি সংখ্যা n মৌলিক কিনা যাচাই করার জন্য , তাহলে উপরের সংজ্ঞা অনুসারে আমরা যেটা করব যে ১ থেকে n সীমার মধ্যে ১ এবং n ছাড়া অন্য কোনো সংখ্যা দিয়ে n নিঃশেষে বিভাজ্য যায় কিনা । অর্থাৎ check করতে হবে যে  n % i == 0 কিনা, যেখানে 2<= i <=n-1. 

এখানে ২ থেকে n-1 কেন নিলাম? কারণ সব সংখ্যাই ১ এবং ওই সংখ্যা দ্বারা  নিঃশেষে বিভাজ্য যায়।


bool Check_if_Prime (int n) {

if(n<=1)return false;

for(int i=2; i<n; i++){

if(n % i == 0){

return false;

}

}

return true;

}


উপরের function টি যখন n এর জন্য call করা হবে , তখন function এর ভিতরের for loop টি ২ থেকে n-1 পর্যন্ত ঘুরবে এবং loop variable i এর প্রতিটি মানের জন্য n % i == 0 কিনা যাচাই করবে। যদি i এর কোনো মানের জন্য n % i == 0 হয়, এর মানে দাঁড়ায় ১ এবং n ছাড়াও n এর অন্য কোনো উৎপাদক আছে । তখন function টি false return করে এর কাজ সমাপ্ত করবে। অন্যথায় পুরো loop ঘুরেও যদি i এর কোন মানের জন্য n % i == 0 না হয় তবে true return করবে। তাহলে function টির time complexity দাঁড়ায় O(n-2) বা O(n) ( যেহেতু complexity হিসাব করার সময় constant value বাদ দেওয়া যায় ) । 


এখন আমরা function টির time complexity কমানোর চেষ্টা করি । প্রথমত খেয়াল করি , যদি ২ দ্বারা n নিঃশেষে বিভাজ্য না হয় তবে n অন্য কোন জোড় সংখ্যা দ্বারাই নিঃশেষে বিভাজ্য হবে না। তাহলে আমাদের function নিচের মতো হতে পারে :


bool Check_if_Prime (int n) {

if(n<=1)return false;

if(n % 2 == 0 && n>2){

return false;

}

for(int i=3; i<n; i+=2){

if(n % i == 0){

return false;

}

}

return true;

}


এক্ষেত্রে আমরা ২ ছাড়া অন্য কোন জোড় সংখ্যার জন্য n এর বিভাজ্যতা যাচাই করিনি । তাহলে আমাদের Check_if_Prime() function এর time complexity হল O(n/2) বা O(n) ( যেহেতু complexity হিসাব করার সময় constant value বাদ দিবো ) . অর্থাৎ কিছুটা optimization হলেও তাত্ত্বিক হিসাবে কোন পার্থক্য হয়নি । 


এখন খেয়াল করি একটি সংখ্যা n এর  উৎপাদক বা গুণনীয়ক যদি a হয় তবে (n/a) ও হবে n এর একটি গুণনীয়ক । 


ধরি b = n/a , যেখানে a হচ্ছে n এর একটি উৎপাদক । 


এখন , n = √n * √n

আবার, n = a * b


যদি a < √n হয় , তবে b কে অবশ্যই √n থেকে বড় হতে হবে ।

আবার যদি a < √n হয় , তবে b কে অবশ্যই √n থেকে ছোট হতে হবে ।

আর যদি a = √n হয় , তবে b অবশ্যই √n এর সমান হবে ।


তাহলে আমরা দেখতে পাচ্ছি যে (a,b) জোড়ায়  a  ও b এর মধ্যে যেকোনো একটি অবশ্যই √n এর সমান অথবা ছোট হবে । একটি উদাহরণ দিলে বিষয়টি আরও স্পষ্ট হবে । আমরা 24 এর উৎপাদকগুলোর দিকে তাকাই :


24 = 1 * 24

     = 2 * 12

     = 3 * 8

     = 4 * 6


আমরা দেখতে পাচ্ছি যে , 24 এর উৎপাদক জোড়াগুলোর মধ্যে সকল জোড়াতেই একটি উৎপাদক √24 এর চেয়ে ছোট বা সমান এই শর্ত মানে। 


তাহলে কোন সংখ্যা মৌলিক না হয়ে যৌগিক (composite) হলে এর অবশ্যই 2 থেকে √n সীমার মাঝে কোন না কোন উৎপাদক থাকবে।  সুতরাং , Check_if_Prime() function এর ভিতরের loop টি √n পর্যন্ত ঘুরালেই আমদের Prime Checking এর কাজটা হয়ে যাচ্ছে । 


bool Check_if_Prime (int n) {

if(n % 2 == 0 && n>2){

return false;

}

for(int i=3; i*i<=n; i+=2){

if(n % i == 0){

return false;

}

}

return true;

}

উপরের code snippet টি একটু খেয়াল করলেই আমরা দেখব যে , loop এর ভিতর আমরা condition হিসেবে   i <= sqrt(n)  ব্যবহার না করে i*i<=n করেছি । এর কারণ হচ্ছে sqrt(n) ব্যবহার করলে অনেক সময় double এর precision এ ঝামেলা করে। যেমন sqrt(9) এর জন্য 3 না এসে 2.9999…. আসতে পারে । তখন 2.9999…. কে integer এ রুপান্তর করলে সেটা 3 না হয়ে 2 হয়ে যাবে । তখন 9 কে মৌলিক সংখ্যা হিসেবে দেখাবে  । 


তাহলে এখন আমাদের Check_if_Prime() function এর time complexity দাঁড়ালো O(√n).এখন এই বিষয়ক একটি Online judge problem (URI 1165) দেখা যাক।


URI 1165 


Problem Link : ( https://www.urionlinejudge.com.br/judge/en/problems/view/1165 )


এই problem এ আমাদেরকে কিছু ইনপুট x এর জন্য , x prime number কিনা তা যাচাই করতে বলেছে। খুব সহজেই আমরা উপরে Check_if_Prime()  function টি ব্যবহার করে x prime কিনা তা বলে দিতে পারি। নিচে এর সমাধান দেওয়া হল :


URI 1165 Solution

#include <bits/stdc++.h>

using namespace std;

bool Check_if_Prime (int n) {

if(n<=1)return false;

if(n % 2 == 0 && n>2){

return false;

            }

            for(int i=3; i*i<=n; i+=2){

if(n % i == 0){

                    return false;

                        }

            }

            return true;

}

int main() {

    int t;

    cin>>t;

    for(int i=0;i<t;i++){

        int x;

        cin>>x;

        if(Check_if_Prime (x)){

            cout<<x<<" eh primo\n";

        }

        else{

            cout<<x<<" nao eh primo\n";

        }

    }

    return 0;

}



অনেক বড় কোন একটি সংখ্যা মৌলিক কিনা তা যাচাই করার জন্য আমরা JAVA তে BigInteger.isProbablePrime(int certainty) method টি ব্যবহার করতে পারি। এক্ষেত্রে পরীক্ষাধীন BigInteger টি যদি মৌলিক-সম্ভাব্য হয় তবে method টি true return করবে , আর যদি যৌগিক হয় তবে false rerturn করবে।


এই সম্পর্কিত একটি problem হল Codeforces 1033B - Square Difference . (Link : https://codeforces.com/contest/1033/problem/B



Codeforces 1033B - Square Difference


এই problem এ আমাদের কিছু test case দেওয়া থাকবে । প্রতিটি test case এ দুটি করে সংখ্যা a ও b দেওয়া থাকবে। আমাদের বলতে হবে (a2 - b2) মৌলিক কিনা । আমরা খুব সহজে JAVA তে  (a2 - b2) এর জন্য BigInteger.isProbablePrime(int certainty) method এর return value যাচাই করে বলে দিতে পারি (a2 - b2) মৌলিক কিনা । নিম্নে এর সমাধান দেওয়া হল :


Codeforces 1033B - Square Difference Solution

import java.util.*;
import java.math.*;

public class Main{
    public static void main(String[] args){
        int t;
        Scanner src = new Scanner(System.in);
        t = src.nextInt();
        for(int i=0;i<t;i++){
            BigInteger a,b;
            a=src.nextBigInteger();
            b=src.nextBigInteger();
           
            if((a.multiply(a).subtract(b.multiply(b))).isProbablePrime(10)){
                System.out.println("YES");
            }
            else{
                System.out.println("NO");
            }
        }
    }
}



উপরের এই problem টি আমরা চাইলে গণিত দিয়ে আরও সহজে করতে পারি। এখানে (a2 - b2) কে আমরা লিখতে পারি  (a+b) * (a-b) আকারে। এখন (a2 - b2) সংখ্যাটি মৌলিক হবে যদি ও কেবল যদি (a+b) ও (a-b) এর যেকোনো একটি মৌলিক হয় এবং অপরটি 1 হয়। যেহেতু a আর b কোনটিই 1 থেকে ছোট নয় , তাই (a+b) অবশ্যই 1 থেকে বড় হবে । অর্থাৎ (a2 - b2) সংখ্যাটিকে মৌলিক হতে হলে (a-b) কে অবশ্যই 1 হতে হবে এবং (a+b) কে অবশ্যই মৌলিক হতে হবে । তাহলে Check_if_Prime() funtion দিয়ে (a+b) মৌলিক কিনা এবং (a-b) যৌগিক কিনা এতটুকু যাচাই করাই যথেষ্ট হবে । নিচে সমাধান দেওয়া হল:


Codeforces 1033B - Square Difference Solution


#include<bits/stdc++.h>


using namespace std;


bool Check_if_Prime (unsigned long long n) {

    if(n<=1ULL)return false;

    if(n % 2ULL == 0 && n>2ULL){

        return false;

    }

    for(unsigned long long i=3; i*i<=n; i+=2ULL){

        if(n % i == 0){

    return false;

        }

    }

    return true;

}

int main(){

    int t;

    cin>>t;

    for(int i=0;i<t;i++){

         unsigned long long a ,b;

         cin>>a>>b;

         if(Check_if_Prime(a+b) && a-b==1){


            cout<<"YES\n";

         }

         else{

            cout<<"NO\n";

         }

    }

}