华师一附中OI组

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1581|回复: 7
打印 上一主题 下一主题

P1010 幂次方

[复制链接]

738

主题

1485

帖子

5420

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5420
跳转到指定楼层
楼主
发表于 2018-5-3 11:28:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
https://www.luogu.org/problemnew/show/P1010

题目描述
任何一个正整数都可以用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)
输入输出格式
输入格式:
一个正整数n(n≤20000)。

输出格式:
符合约定的n的0,2表示(在表示中不能有空格)

输入输出样例
输入样例#1:
1315
输出样例#1:
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)
回复

使用道具 举报

738

主题

1485

帖子

5420

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5420
推荐
 楼主| 发表于 2018-5-5 19:47:21 | 只看该作者
当然,有创新者,发现N<=20000,意思就是不会超过2^15,于是打个1-2^15的表,然后查表的结果,这也是做法之一,就不吐代码了。
  1. #include <iostream>
  2. using namespace std;
  3. string s[16];
  4. int i,x,a[16];
  5. int main()
  6. {
  7.     ///这也太搞笑了吧!!!
  8.     s[0]="2(0)";       ///1
  9.     s[1]="2";          ///2
  10.     s[2]="2(2)";       ///4
  11.     s[3]="2(2+2(0))";   ///8
  12.     s[4]="2(2(2))";
  13.     s[5]="2(2(2)+2(0))";
  14.     s[6]="2(2(2)+2)";
  15.     s[7]="2(2(2)+2+2(0))";
  16.     s[8]="2(2(2+2(0)))";
  17.     s[9]="2(2(2+2(0))+2(0))";
  18.     s[10]="2(2(2+2(0))+2)";
  19.     s[11]="2(2(2+2(0))+2+2(0))";
  20.     s[12]="2(2(2+2(0))+2(2))";
  21.     s[13]="2(2(2+2(0))+2(2)+2(0))";
  22.     s[14]="2(2(2+2(0))+2(2)+2)";
  23.     cin>>x;
  24.     i=0;
  25.     while (x>0)
  26.     {
  27.         a[i]=x%2;
  28.         x=x/2;
  29.         i++;
  30.     }
  31.     i=15;
  32.     while (a[i]==0) i--;
  33.     cout<<s[i];
  34.     i--;
  35.     for (; i>=0; i--)
  36.         if (a[i]==1) cout<<'+'<<s[i];
  37.     return 0;
  38. }
复制代码


回复 支持 1 反对 0

使用道具 举报

738

主题

1485

帖子

5420

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5420
推荐
 楼主| 发表于 2018-5-5 19:43:01 | 只看该作者
拼凑出程序,还要自己检查,这个很好办,自己运行x=1--100,手动检查若无问题,即做法正确。
回复 支持 1 反对 0

使用道具 举报

738

主题

1485

帖子

5420

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5420
地板
 楼主| 发表于 2018-5-3 13:46:45 | 只看该作者
沙发

  1. #include<iostream>
  2. using namespace std;
  3. void ms(int x)
  4. {
  5.     ///求出x=2^m+n的m和n
  6.     int m=0,n=0,s=1;
  7.     while (x>=s){s=s*2;m++;} ///越过后再回头是一种做法
  8.     m--;s=s/2;
  9.     n=x-s;
  10.     ///分情况递归
  11.     if (m==0) cout<<"2(0)";
  12.     else if (m==1) cout<<"2";
  13.     else
  14.     {
  15.         cout<<"2(";
  16.         ms(m);  ///递归
  17.         cout<<")";
  18.     }

  19.     if (n>0)
  20.     {
  21.         cout<<'+';    ///分解剩下的那个小尾巴
  22.         ms(n);
  23.     }
  24. }
  25. int main()
  26. {
  27.     for (int x=1; x<=20; x++)
  28.     {
  29.         ms(x);
  30.         cout<<endl;
  31.     }
  32.     return 0;
  33. }


复制代码

回复 支持 反对

使用道具 举报

738

主题

1485

帖子

5420

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5420
5#
 楼主| 发表于 2018-5-5 19:39:33 | 只看该作者
做题过程:
经过分析,每个数字x都可以分解成2^m+n的唯一形式,因为要求m最大。然后递归就是
主程序
void  ms(int x)
{
   分解出m和n
   再递归  m=0,1 无法递归。
   n=0不需要递归
}
写出这一段的框架备用
回复 支持 反对

使用道具 举报

738

主题

1485

帖子

5420

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
5420
6#
 楼主| 发表于 2018-5-5 19:42:02 | 只看该作者
怎么求出m呢?仿照s=1+2+4+7+***的那个题,就是求出2^m<=x的最大m
一种常规做法。不断的乘,直到大于,然后减1。
while (x>=s){s=s*2;m++;} ///越过后再回头是一种做法
    m--;s=s/2;
n就是x-2^m
这段代码填入
回复 支持 反对

使用道具 举报

50

主题

215

帖子

619

积分

高级会员

Rank: 4

积分
619
7#
发表于 2018-7-4 20:09:17 | 只看该作者
  1. #include<iostream>
  2. using namespace std;
  3. int i,n,s,a[20001]={},j=0;
  4. int cf(int a,int b)
  5. {
  6.     int c=2;
  7.     for(int x=2;x<=b;x++)c*=2;
  8.     if(b==0)c=1;
  9.     return c;
  10. }
  11. void kj(int e)
  12. {
  13.     int k=1,y;
  14.     if(e==0)return;
  15.     i=0;
  16.     j++;
  17.     do i++;
  18.     while(cf(2,i)<=e);
  19.     y=--i;
  20.     a[j]=y;
  21.     if(a[j]==0)cout<<"2(0)";
  22.     if(a[j]==1)cout<<"2";
  23.     if(a[j]>1)
  24.     {
  25.         cout<<"2(";
  26.         kj(a[j]);
  27.         cout<<")";
  28.     }
  29.     if(e!=cf(2,y))
  30.     {
  31.         cout<<"+";
  32.         kj(e-cf(2,y));
  33.     }
  34. }
  35. int main()
  36. {
  37.     cin>>n;
  38.     kj(n);
  39. }
复制代码
回复 支持 反对

使用道具 举报

14

主题

106

帖子

317

积分

中级会员

Rank: 3Rank: 3

积分
317
8#
发表于 2018-11-24 17:53:27 | 只看该作者
  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cmath>
  4. using namespace std;
  5. #define FOR(i,a,b) for(register int i=a;i<=b;++i)
  6. #define For(i,a,b) for(register int i=a;i>=b;--i)
  7. void dg(int x)
  8. {
  9.     if(x==0) {cout<<0;return;}
  10.     if(x==2) {cout<<2;return;}
  11.     int logg=floor(log(x)*1.00/log(2.00));
  12.     ///cout<<endl<<x<<" "<<logg<<endl;
  13.     bool flag=0;
  14.     For(i,logg,0) if((1<<i)&x)
  15.     {
  16.         if(flag) cout<<"+";flag=1;
  17.         if(i==1)cout<<"2";
  18.         else{cout<<"2(";dg(i);cout<<")";}
  19.     }
  20. }
  21. int main()
  22. {
  23.     int n;scanf("%d",&n);
  24.     dg(n);return 0;
  25. }
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|服务支持:DZ动力|华师一附中OI组  

GMT+8, 2024-11-2 04:26 , Processed in 0.138227 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表