NOIP1998普及組複賽第二題 貳的冪方 解題報告

【問題描述】  
  
任何一個正整數都可以用 2 的冪次方表示。例如:137=27+23+20。
  在這裏我們約定次方用括號來表示,即 ab 可表示爲 a(b)。
  由上面敘述可知:137 又可以表示爲 2(7)+2(3)+2(0)。進一步:7=22+2+20=2(2)+2+2(0)(21用2表示)。3=2+20=2+2(0)。所以最後137可表示爲:2(2(2)+2+2(0))+2(2+2(0))+2(0)。
  又如:1315=210+28+25+2+1。
  所以1315最後可表示爲:2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)。 


 
  【輸入格式】  
  
  包含若干組數據,每組數據佔一行,每行一個正整數n。
 
    
 【輸出格式】  
   
  輸出每組數輸出一行,是符合約定的 n 的 0,2 表示(在表示中不能有空格)。


 【輸入樣例】   
   
137
1315


【輸出樣例】  
   
2(2(2)+2+2(0))+2(2+2(0))+2(0)
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)


【數據範圍】  
   
n <= 2^31

 【來源】  
  
NOIP1998普及組複賽第二題


 解題思路:本題的主要算法爲分治算法,對於每輸入一個數,我們可以先把它分解爲2的冪方的和,然後將指數大於2的繼續分解。需要注意的是,本題中n的範圍最大爲2^31,超過了int的範圍(2^31-1),所以n定義爲long long,並且,在計算2^31時,要麼直接用1<<31然後強制類型轉換爲long long,要麼可以先計算出1<<30,再將得到的值乘2。


#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=35;
long long N;  //定義爲long long
void solve(long long x)
{
	int ok=0;  //用來記錄是否已經輸出過值,以控制輸出'+'
	for(int i=31;i>=0;i--)
	{
		long long k;
		if(i<31)  k=1<<i;
		else  //計算2^31
		{
			k=1<<30;
			k=k*2;
		}
		if(x>=k && i>2) 
		{
			if(ok==1)  printf("+");  
			printf("2(");
			solve(i);  //指數大於2,繼續分解
			printf(")");
			ok=1;
			x-=k;
		}
		if(x>=k && i==2)  
		{
			if(ok==1)  printf("+");
			printf("2(2)");
			ok=1;
			x-=k;
		}
		if(x>=k && i==1)
		{
			if(ok==1)  printf("+");
			printf("2");
			ok=1;
			x-=k;
		}
		if(x>=k && i==0)
		{
			if(ok==1)  printf("+");
			printf("2(0)");
			ok=1;
			x-=k;
		}
	}
}
int main()
{
	freopen("48.in","r",stdin);
	//freopen("48.out","w",stdout);
	while(cin>>N)  
	{
		solve(N);
		printf("\n");
	}
	return 0;
}


發佈了57 篇原創文章 · 獲贊 8 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章