ডিভিসর এর সংখ্যা নির্নয়

June 24, 2017    ডিভিসর প্রাইম ফ্যাক্টর Number Theory Programming

সাধারনত আমরা কোন সংখ্যার কতগুলো ডিভিসর আছে তা নির্নয় এর জন্য লুপ চালায় কাউন্ট করি। কিন্তু n যদি 10^12 হয় তখন কি আমরা এত বার লুপ চালায় কাউন্ট করব?? না , কারন এর ফলে প্রোগ্রাম অনেক ধীরগতির হয়ে যাবে এবং অনলাইন জাজ এ time limit exceed আসবে। তাহলে উপায় কি??

সুত্রঃ

ডিভিসর সংখ্যা নির্নয় এর জন্য প্রথমে n এর প্রাইম ফ্যাক্টর গুলো বের করে নিতে হবে। যে কোন সংখ্যা n হলে n কে আমরা প্রাইম সংখ্যার গুনফল আকারে লিখতে পারি। যেমনঃ n=১২ হলে, \(12= 2 \times 2 \times 3\)

এখানে প্রাইম ফ্যাক্টরগুলো হলঃ 2, 2 , 3

এখন, \(12= 2^2 \times 3^1\)

তাহলে , Number Of Divisors=d

                           d= ((2 এর পাওয়ার)+1)*((3 এর পাওয়ার)+1)

                              =(2+1)*(1+1)

                              =6

সুতরাং , \(n= P_1^{x1}\times P_2^{x2}\times P_3^{x3}\times ……………………………………….P_n^{xn}\) হলে

ডিভিসর সংখ্যা , d= (x1+1)*(x2+1)*(x3+1)*……………………………..(xn+1)

প্রাইম ফ্যাক্টর বের করার নিয়মঃ

প্রথমে 1 থেকে sqrt(10^12) পর্যন্ত সব প্রাইম নম্বর জেনারেট করে ফেলব সিভ sieve এলগরিদম দিয়ে।

এখানে sqrt পর্যন্ত নেয়া হয়েছে কারন 10^12 এর প্রাইম ফ্যাক্টর গুলো sqrt(10^12) এর মধ্যেই থাকবে যেমন ১২ এর প্রাইম ফ্যাক্টর sqrt(12)=3 এর মধ্যেই থাকে ।

এখন প্রাইম জেনারেট করার সময় অবশ্যই p এরেতে স্টোর করে রাখব। p এরের সাইজ বের করে ফেলব।

এখন প্রাইম ফ্যাক্টর বের করার জন্য চেক করতে হবে প্রাইম নম্বরগুলো দিয়ে n ভাগ যায় কি না। ভাগ গেলে আমরা প্রাইম ফ্যাক্টর কাউন্ট করব।

সর্বোচ্চ এরের সাইজ k পর্যন্ত লুপ চলবে কিন্তু আমরা তার আগেই লুপ শেষ করতে পারি কারন 12 এর ক্ষেত্রে এরের মান sqrt(12) কে অতিক্রম করবে না।

এরপর লুপ এ n%p[i]==0 কি না চেক করে বের করব ।

while(n%p[i]==0)
{
  count++;
}

যদি n=0 অথবা ১ হয়ে যায় তাহলে break করব লুপ ।

যেমনঃ

726= 2*3*11*11

n=(726/2)=363

2 এর জন্য count=1

n=(363/3)=121

3 এর জন্য count=1

n=(121/11)=11

n=(11/11)=1

11 এর জন্য count=2

n=1 তাই ব্রেক হবে ।

সুতরাং d=(1+1)*(1+1)*(2+1)=12

Code

#include <bits/stdc++.h>
using namespace std;
#define n 1000005
bool a[n];
long long int k=1;
long long int twin[n];
void sieve()
{
    long long int i,j;
    a[0]=a[1]=1;
    for(i=4;i<=n;i=i+2)
    {
        a[i]=1;
    }
    for(i=3;i<=sqrt(n);i=i+2)
    {
        for(j=i*i;j<=n;j=j+2*i)
        {
            a[j]=1;        //3*3, 3*5,3*7.....
        }
    }
    for(i=2;i<=n;i++)
    {
        if(a[i]==0)
        {
           twin[k]=i;
           k++;
        }
    }

}
int main()
{
    long long int m,g,c,r,s,t,l,h;
    cin>>t;
    sieve();
    for(l=1;l<=t;l++)
    {
        cin>>m;
        //in>>m;
        r=1;
        h=0;
        for(g=1;g<=k && twin[g]<=sqrt(m);g++)
        {
            c=0;
            if(m%twin[g]==0)
            {

            while(m%twin[g]==0)
            {
                c++;
                m=m/twin[g];
                if(m==0 || m==1)
                {
                    break;
                }

             }
              s=c+1;
              r=r*s;
            }



        }
        if(m!=1)
        {
            r=r*2;    //for prime numbers there are only 2 divisors.
        }

        printf("%lld\n",r);
        

    }

    return 0;
}

UVA 294 Divisors এবং LightOj 1028 Trailing Zero (1)

এর প্রব্লেম এই নিয়মে সল্ভ করা যায়। কোডিং এ প্রব্লেম হলে UVA 294 Divisors এবং LightOj 1028 Trailing With Zeroes(I) এর সলুশন দেখতে পারো ।


blog comments powered by Disqus
Fork me on GitHub