洛谷Oj-幂次方-分治

来源:互联网 发布:ajax跨域post请求数据 编辑:程序博客网 时间:2024/05/16 01:30

问题描述
任何一个正整数都可以用2的幂次方表示。例如
137=2^7+2^3+2^0
同时约定方次用括号来表示,即a^b 可表示为a(b)。
由此可知,137可表示为:
2(7)+2(3)+2(0)
进一步:7= 2^2+2+2^0 (2^1用2表示)
3=2+2^0
所以最后137可表示为:
2(2(2)+2+2(0))+2(2+2(0))+2(0)
又如:
1315=2^10 +2^8 +2^5 +2+1
所以1315最后可表示为:
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
AC代码

int a[]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768};//因为n≤20000,所以将2的幂次打表void fun(int n){    while(n!=0)//n不为0时执行while循环,因为n可以用2的幂次方表示(等价于转换为二进制),所以n最后一定会变为0然后跳出循环    {        int i,m;//i是循环变量,m是当前2的幂次        for(i=0;;i++)            if(n<a[i])//比如n==3000时,n<4096=2^12,所以n可以表示为2^11+......,m此时为11            {                m=i-1;                n=n-a[i-1];//将2^m从n中减去                break;//跳出循环            }        if(m==0)//边界条件            printf("2(0)");        else if(m==1)//边界条件            printf("2");        else//一开始一般来说执行这条语句,因为n一般比较大        {            printf("2(");            fun(m);//递归调用,解决规模比原问题小的子问题,子问题的解法同原问题            printf(")");        }        if(n!=0)当n不为0时,执行一次while循环便打印一个‘+’            printf("+");    }   }int main(){    int n;    scanf("%d",&n);//输入n    fun(n);    printf("\n");//换行    return 0;}

算法描述:
①请从main函数看起,这是一个好习惯。
②边界条件加上
else if(m==2)
printf(“2(2)”);
当然也可以
③分治思想一般的算法设计模式如下:

Divide-and-Conquer(P)

  1. if |P|≤n0

  2. then return(ADHOC(P))

  3. 将P分解为较小的子问题 P1 ,P2 ,…,Pk

  4. for i←1 to k

  5. do yi ← Divide-and-Conquer(Pi) △ 递归解决Pi

  6. T ← MERGE(y1,y2,…,yk) △ 合并子问题

  7. return(T)

其中|P|表示问题P的规模;n0为一阈值,表示当问题P的规模不超过n0时,问题已容易直接解出,不必再继续分解。ADHOC(P)是该分治法中的基本子算法,用于直接解小规模的问题P。因此,当P的规模不超过n0时直接用算法ADHOC(P)求解。算法MERGE(y1,y2,…,yk)是该分治法中的合并子算法,用于将P的子问题P1 ,P2 ,…,Pk的相应的解y1,y2,…,yk合并为P的解。