ブロガーのホームページ: Yu・Xiansheng
コラムアドレス:羅谷千問の詳しい解説
目次
-------------------------------------------------- -------------------------------------------------- -------------------------
-------------------------------------------------- -------------------------------------------------- -------------------------
質問の説明
任意の正の整数は 2 のべき乗として表現できます。たとえば、137=27+23+20。
同時に、べき乗は括弧で表されること、つまり、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)。
-------------------------------------------------- -------------------------------------------------- -------------------------
入力フォーマット
1 行につき 1 つの正の整数 n。
-------------------------------------------------- -------------------------------------------------- -------------------------
出力フォーマット
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)
-------------------------------------------------- -------------------------------------------------- -------------------------
分析:
2 進数は、実際には 2 のべき乗の和に分解された正の整数を表すことがわかっています。
例えば、3は2進数で11と表され、右から0桁目、1桁目…となります。
次に、 3=2^1+2^0 (バイナリビットが 1 である限り、2^(このビット))
別の例として、2 進数の 10 は 1010 なので、10=2^3+2^1 になります。
実際に体験してみましょう
以下はより高度です: ビット操作 (実際には高度ではありませんが、誰もそれを行いません)
ビット演算のやり方が分からない場合は上記を使用してください個人的にはビット演算の方が速いと思います(通常14ms、ビット演算11ms)
ビット演算の詳細については Du Niang にお問い合わせください。
考え方は次のとおりです。
n の 2 進数を (下位から上位まで) 調べ、配列を使用してビットが 1 である桁数を格納します。たとえば、1010 (つまり 10)、最初のビットが 1 であることを最初に記録します。 、最後に 3 番目のビットが 1 であることを記録します。
トラバーサルが完了すると、上位ビットが最初に処理されます (つまり、元々は i++ でしたが、現在は i-- になります)。
このビット (つまり、累乗の数) が 2 より大きいため、再帰が再度処理されます。
ビットが 3 未満になるように処理されたら、出力します。
-------------------------------------------------- -------------------------------------------------- -------------------------
C++ ソース コード:
#include<cstdio>
using namespace std;
void ASCII(int m)
{
int i=0,k=m,u=0,h[50];
while(k)//位运算实现;
{
if(k&1)h[++u]=i;
//h[++u]相当于++u,h[u]……
k>>=1;
i++;
}
//据上面写的,u从1开始,无论如何一定会有输出;
while(u)//u为真
{
if(h[u]<3)//具体括号判断;
{
if(h[u]==1 && u-1!=0) printf("2+");
else if(h[u]==1) printf("2");
if((h[u]==0||h[u]==2)&&(u-1!=0)) printf("2(%d)+",h[u]);
else if(h[u]==0||h[u]==2) printf("2(%d)",h[u]);
--u;//搜索下一个;
}
else
{
printf("2(");
ASCII(h[u--]);
//相当于h[u],--u;
//这里千万不能写成 h[--u],否则你会3个WA两个MLE;
if(u!=0)printf(")+");
//由于u进行了自减,此时的u已经是下一个数了;
else printf(")");
//判断括号;
}
}
}
int main()
{
int n;
scanf("%d",&n);
ASCII(n);
return 0;//别忘了写;
}
-------------------------------------------------- -------------------------------------------------- -------------------------
パスカルのソースコード:
type num=array[0..100000] of longint;
var i,j,k,l,n,m,o,p,h:longint;
//这里的a[0]指数组长度。
function ejz(s:longint):num;//要转的数
var i,j,k:longint;
ans:num;
begin
i:=s; j:=0; k:=0; //让变量i赋值为要转的数s
fillchar(ejz,sizeof(ejz),0);
fillchar(ans,sizeof(ans),0);
while i>0 do
begin
inc(j);
ejz[j]:=i mod 2;
i:=i div 2; //转2进制的过程在此。
end;
for i:=j downto 1 do
if ejz[i]=1 then begin inc(k); ans[k]:=i-1; end;//若2进制的第n位为1,那么数组中必有n-1。这个应该知道吧
ans[0]:=k;
exit(ans);
end;
procedure search(a:longint);
var n:num; i:longint;
begin
if a=0 then begin write('2(0)'); exit; end; //如果要处理0,那么...
if a=1 then begin write('2'); exit; end; //如果要处理1,那么...
n:=ejz(a);
for i:=1 to n[0]-1 do
begin
if (n[i]<>1) and (n[i]<>0) then write('2(');//这里要注意了!2^1不是2(1)!!!
search(n[i]);//递归处理数组里的数
if (n[i]<>1) and (n[i]<>0) then write(')');
write('+');//不要把加号输多了!
end;
if (n[n[0]]<>1) and (n[n[0]]<>0) then write('2(');
search(n[n[0]]);
if (n[n[0]]<>1) and (n[n[0]]<>0) then write(')');
end;
begin
readln(n);
search(n);
end.
-------------------------------------------------- -------------------------------------------------- -------------------------
Java ソース コード:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc= new Scanner(System.in);
int a=sc.nextInt();
pow(a);
}
public static void pow(int a){
if(a>3){
int s=0;
int b=2;
while(b<=a){
b=b*2;
s++;
}
a=a-b/2;
System.out.print("2(");
pow(s);
if(s==3){
System.out.print("2+2(0)");
}
if(s==1){
System.out.print("2(0)");
}
if(s==2){
System.out.print("2");
}
System.out.print(")");
if(a==3){
System.out.print("+2+2(0)");
}
if(a==1){
System.out.print("+2(0)");
}
if(a==2){
System.out.print("+2");
}
if(a>3){
System.out.print("+");}
pow(a);
}
}
}
-------------------------------------------------- -------------------------------------------------- -------------------------
Python ソースコード:
def f1(x):
##获取一个数的幂
str0 = bin(int(str(x), 10))
str1 = str0[2:]
list1 = []
index = 0
for i in str1[::-1]:
if i == '1':
list1.append(index)
index += 1
list1.reverse()
return list1
def f2(list):
##格式化输出
list1 = [str(i) for i in list]
str2 = ''
for i in range(len(list1)):
if i < len(list1) - 1:
if list1[i] == "1":
str2 += "2+"
else:
if list[i] != 0:
str2 += "2({})+".format(f2(f1(list[i])))
else:
str2 += "2(0)"
if i == len(list1) - 1:
if list1[i] == "1":
str2 += "2"
else:
if list[i] != 0:
str2 += "2({})".format(f2(f1(list[i])))
else:
str2 += "2(0)"
return str2
n=int(input())
print(f2(f1(n)))
-------------------------------------------------- -------------------------------------------------- -------------------------