POJ 1906

题意:题目给出一个集合{3^0,3^1,3^2,3^3,3^4,3^5,3^6,···,3^n},以其所有子集中各元素之和为基准,从小到大排列该集合的所有子集:
{ },{ 1 },{ 3 },{ 1, 3 },{ 9 },{ 1, 9 },{ 3, 9 },{ 1, 3, 9 },{ 27 },{ 1, 27 },{ 3, 27 },{ 1, 3, 27 },{ 9, 27 },{ 1, 9, 27 },{ 3, 9, 27 },{ 1, 3, 9, 27 }···

其和为别为:0,1,3,4,9,10,12,13,27,28,30,31,36,37,39,40···

为别对应位置:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16···

题目要求输入一个数字a(位置),输出该位置上相应的集合。

经观察,发现:2^n<a<=2^n+1时,待输出位置上的集合中必有元素3^n。沿用这个思路,每输出一个3^n,a减少2^n,减少到a==1为止(1号位置的不用输出)。

题目要求输入的a不超过19位,因为2^65为20位数字,则原集合中最多有64个元素,其中最大元素的是3^63。因为3^63不超过32位,则开一个字符型数组data[65][32],data[0]中存"\0",data[1]至data[64]中存3^0至3^63。

字符数组data[65][32],采用本地指标方式进行了初始化(为了省时省空间)。
下面是制表代码:

#include<iostream>
#include<string>
#include<cstring>
using namespace std;

const int size=1000;  //大数位数

void mult(char* A,char* B,char* ans)
{
   int a[size+1]={0};
   int b[size+1]={0};
   int pa=0,pb=0;
   int c[2*size+1]={0};

   int lena=strlen(A);
   int lenb=strlen(B);

   for(int i=lena-1;i>=0;i--)
       a[pa++]=A[i]-'0';
   for(int j=lenb-1;j>=0;j--)
       b[pb++]=B[j]-'0';

   for(pb=0;pb<lenb;pb++)
   {
       int w=0;  //低位到高位的进位
       for(pa=0;pa<=lena;pa++)
       {
           int temp=a[pa]*b[pb]+w;
           w=temp/10;
           temp=(c[pa+pb]+=temp%10);
           c[pa+pb]=temp%10;
           w+=temp/10;
       }
   }
   bool flag=false;
   bool sign=false;  //标记ans是否为全0
   for(pa=0,pb=lena+lenb-1;pb>=0;pb--)
   {
       if(!flag && c[pb]==0)  //删除ans开头的0
           continue;
       else
           flag=true;

       sign=true;
       ans[pa++]=c[pb]+'0';
   }
   if(sign)
       ans[pa]='\0';
   else
   {
       ans[0]='0';
       ans[1]='\0';
   }

   return;
}

char a[size+1];
char ans[size*size+1];

int main(void)
{
   int b;
   for(b=0;b<64;b++)
   {
       a[0]='3';
       ans[0]='1';
       ans[1]='\0';
       for(int i=1;i<=b;i++)
           mult(a,ans,ans);
       cout<<"""<<ans<<"""<<",";
   }
   return 0;
}

将输出粘贴复制进data[65][32]数组中即可(⊙o⊙)…



接着是本体的代码:

#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
int process(double n)    //取出元素3^i-1,即data[i]
{
   double i=0,t=1;
   while(t<n)
   {
       t*=2;
       i++;
   }
   return i;
}
int main()
{
   int temp,j;
   double n;
   char result[65][32],data[65][32]={"\0","1","3","9","27","81","243","729","2187","6561",
       "19683","59049","177147","531441","1594323","4782969","14348907",
       "43046721","129140163","387420489","1162261467","3486784401",
       "10460353203","31381059609","94143178827","282429536481","847288609443",
       "2541865828329","7625597484987","22876792454961","68630377364883","205891132094649",
       "617673396283947","1853020188851841","5559060566555523","16677181699666569",
       "50031545098999707","150094635296999121","450283905890997363","1350851717672992089",
     "4052555153018976267","12157665459056928801","36472996377170786403","109418989131512359209",
  "328256967394537077627","984770902183611232881","2954312706550833698643","8862938119652501095929", "26588814358957503287787","79766443076872509863361","239299329230617529590083","717897987691852588770249", "2153693963075557766310747","6461081889226673298932241","19383245667680019896796723","58149737003040059690390169", "174449211009120179071170507","523347633027360537213511521","1570042899082081611640534563","4710128697246244834921603689", "14130386091738734504764811067","42391158275216203514294433201","127173474825648610542883299603","381520424476945831628649898809",
"1144561273430837494885949696427"};
   while(cin>>n&&n!=0)
   {
       j=0;
       while(n>1)
       {
           temp=process(n);
           strcpy(result[j++],data[temp]);
           n-=pow(2.0,temp-1);
       }
       if(j==0)cout<<"{ }"<<endl;
       else
       {
           cout<<"{ ";
           while(j>1)
               cout<<result[--j]<<", ";
           cout<<result[--j]<<" }"<<endl;
       }
   }
   return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值