使用二进制的思想降低时间复杂度

如何使用二进制解决问题

正如通过高精度模拟可以获得500位以上的加减乘除运算外,当对于过大范围的运算我们可以将问题转化为二进制从而简便运算,使运算的一部分复杂度由n转化为log(n)
- 首先是我们熟知的快速排序,即通过不断得将要排序的数组进行中等划分,进而递归成更小的数组,最后获得一个排序完的数组,qsort()其实就可以实现这个过程,不过手打的话可以更清楚一些。
code

void quiksort(int a[],int low,int high)
{
    int i = low;
    int j = high;  
    int temp = a[i]; 

    if( low < high)
    {          
        while(i < j) 
        {
            while((a[j] >= temp) && (i < j))
            { 
                j--; 
            }
            a[i] = a[j];
            while((a[i] <= temp) && (i < j))
            {
                i++; 
            }  
            a[j]= a[i];
        }
        a[i] = temp;
        quiksort(a,low,i-1);   //不断的将数组递归成更小的数组
        quiksort(a,j+1,high);
    }
    else
    {
        return;
    }
}
  • 取余运算
    输入b,p,k的值,编程计算b^p mod k的值。其中的b,p,k*k为长整型数(2^31范围内)。(参见codevs 1497)
    这里如果每一步相乘然后取余的话那么会有一组数据过不了,至于为什么只有一组数据,我也不想说什么,好像codevs的数据一直很友好。那么对于2^31那么至少要运算10^9,而计算机每秒约运算10^6次,明显要算个2,3分钟。所以此时可以考虑使用二进制将运算的复杂度降低为log(n)。
  • 题解
    首先对一开始的p转化为二进制,然后对每次取余后的值平方,从而获得2^k次的运算结果,同时用一个数组保存这个结果,最后将这个结果与原先的p的二进制进行匹配,这样至多就只需要进行31次运算了.
  • code
#include
#include
using namespace std;
int num[100]={0};
int num1[100]={0};
int main(void)
{
    long long b,p,k,sum=1;
    cin>>b>>p>>k;
    long long m=b%k,count=0,ans=p;
    while(p!=0)
    {
        num[count]=p%2;
        p/=2;
        count++;
    }
    for(int i=1;i<count;i++)
    {
        m*=m;
        m%=k;
        num1[i]=m;
    }
    for(int i=count-1;i>=1;i--)
    {
        if(num[i])
        {
            sum*=num1[i];
            sum%=k;
        }
    }
    if(ans%2)
        sum*=b; 
    cout<'^'<" mod "<'='<<sum%k<

你可能感兴趣的:(算法入门)