您的位置:首页 > 其它

POJ 2116解题报告

2015-02-27 23:30 295 查看
Death to Binary?

Time Limit: 1000MSMemory Limit: 65536K
Total Submissions: 1494Accepted: 461
Description

The group of Absurd Calculation Maniacs has discovered a great new way how to count. Instead of using the ordinary decadic numbers, they use Fibonacci base numbers. Numbers in this base are expressed as sequences of zeros and ones similarly to the binary numbers,
but the weights of bits (fits?) in the representation are not powers of two, but the elements of the Fibonacci progression (1, 2, 3, 5, 8,... - the progression is defined by F0 = 1, F1 = 2 and the recursive relation Fn = Fn-1 + Fn-2 for
n >= 2).

For example 1101001Fib = F0 + F3 + F5 + F6 = 1 + 5 + 13 + 21 = 40.

You may observe that every integer can be expressed in this base, but not necessarily in a unique way - for example 40 can be also expressed as 10001001Fib. However, for any integer there is a unique representation that does not contain two adjacent
digits 1 - we call this representation canonical. For example 10001001Fib is a canonical Fibonacci representation of 40.

To prove that this representation of numbers is superior to the others, ACM have decided to create a computer that will compute in Fibonacci base. Your task is to create a program that takes two numbers in Fibonacci base (not necessarily in the canonical representation)
and adds them together.

Input

The input consists of several instances, each of them consisting of a single line. Each line of the input contains two numbers X and Y in Fibonacci base separated by a single space. Each of the numbers has at most 40 digits. The end of input is not marked in
any special way.
Output

The output for each instance should be formated as follows:

The first line contains the number X in the canonical representation, possibly padded from left by spaces. The second line starts with a plus sign followed by the number Y in the canonical representation, possibly padded from left by spaces. The third line
starts by two spaces followed by a string of minus signs of the same length as the result of the addition. The fourth line starts by two spaces immediately followed by the canonical representation of X + Y. Both X and Y are padded from left by spaces so that
the least significant digits of X, Y and X + Y are in the same column of the output. The output for each instance is followed by an empty line.

Sample Input
11101 1101
1 1

Sample Output
100101
+   10001
  -------
  1001000

   1
+  1
  --
  10

Source

CTU Open 2004

这道题是一道比较有趣的题,可以利用斐波那契数列的一些性质来求解。有些人的做法是先将输入的两串数列化为两个十进制数字,再计算其和,得到三个十进制数字,对于每个十进制数字,按照公式:F
<=NUM<F[N+1](F
表示第N个斐波那契数);NUM-=F
;进行迭代,直到NUM==0为止。这些需要计算斐波那契数列的值。代码写起来也比较短。

当然,不这样做也行。我们可以从式子的相加以及变换中找到一些规律,第一个规律就是F(1)=2*F(0),即从右向左,第二位(对应F(1))的数是第一位(对应F(0))数的2倍。这显而易见,F(1)=2,F(0)=1。其次就是最常见的式子,F(k+2)=F(k+1)+F(k),这个式子可以将相邻的两个1变为0,将1的值进位到更高的位。还有一个式子2*F(k+2)=2*F(k+1)+2*F(k)=F(k+1)+F(k)+F(k+1)+F(k)=F(k+2)+F(k+1)+F(k)=F(k+3)+F(k),我们就可以得到2*F(k+2)=F(k+3)+F(k),当然,进行变换以后就可以写成2*F(k)=F(k+1)+F(k-2)(k>=2),因为F(2)=3,F(1)=2,F(0)=1,则F(1)=F(2)+F(0)不满足上式。

这样我们只要这几个有用的递推关系式就可以对数字进行处理从而得出答案。在对数字进行处理时,需要先从高位向低位处理一遍,将相邻的1拆开,但是单纯进行一次遍历还可能导致出现相邻的1,比如,101011,从高位向低位处理以后仍然存在相邻的1,所以还需要再从低位向高位再处理一遍。这样才能保证不存在相邻的1。对三个数按照同样方法处理即可。当然,还需要注意除去前导0。类似于大数加法,还需要考虑在除去前导0时,如果这个数本来就为0的情况。因此要注意两个加数中有1个0,两个0的情况。考虑这种特殊数据。

方法1参考代码

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<ctime>
#include<cstdlib>
#include<iomanip>
#include<utility>
#define pb push_back
#define mp make_pair
#define CLR(x) memset(x,0,sizeof(x))
#define _CLR(x) memset(x,-1,sizeof(x))
#define REP(i,n) for(int i=0;i<n;i++)
#define Debug(x) cout<<#x<<"="<<x<<" "<<endl
#define REP(i,l,r) for(int i=l;i<=r;i++)
#define rep(i,l,r) for(int i=l;i<r;i++)
#define RREP(i,l,r) for(int i=l;i>=r;i--)
#define rrep(i,l,r) for(int i=1;i>r;i--)
#define read(x) scanf("%d",&x)
#define put(x) printf("%d\n",x)
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<11
using namespace std;

char a[50],b[50],c[50];
int f[50];
char fa[50],fb[50],fc[50];
void solve(char a[],int sum)
{
    while(sum>0)
    {
        int t=lower_bound(f,f+45,sum)-f,ans=f[t];
        if(ans>sum) a[t-1]=1,sum-=f[t-1];
        else a[t]=1,sum-=f[t];
    }
}

void print(char a[],int t,int ka,int km)
{
    int k=45;
    if(t==2) printf("+ ");
    else
    {
        printf("  ");
        if(t==3)
        {
            REP(i,0,km)
              printf("-");
            printf("\n");
            return;
        }
    }
    if(ka>=0)
    {
        rep(i,0,km-ka)
           printf(" ");
        RREP(i,ka,0)
           printf("%d",a[i]);
        printf("\n");
    }
    else
    {
        rep(i,0,km)
           printf(" ");
        printf("0\n");
    }
    if(t==4)
        printf("\n");
}

int main()
{
    f[0]=1,f[1]=2;
    rep(i,2,45)
       f[i]=f[i-1]+f[i-2];
    while(~scanf("%s%s",a,b))
    {
        int k1=strlen(a),k2=strlen(b);
        int sum1=0,sum2=0,sum=0;
        CLR(fa);CLR(fb);CLR(fc);
        rep(i,0,k1)
           if(a[i]=='1')
               sum1+=f[k1-1-i];
        rep(i,0,k2)
           if(b[i]=='1')
               sum2+=f[k2-1-i];
        sum=sum1+sum2;
        solve(fa,sum1);solve(fb,sum2);solve(fc,sum);
        int ka=45,kb=45,kc=45,k=0;
        while(ka>=0&&fa[ka]==0) ka--;
        while(kb>=0&&fb[kb]==0) kb--;
        while(kc>=0&&fc[kc]==0) kc--;
        k=max(k,ka);k=max(k,kb);k=max(k,kc);
        print(fa,1,ka,k);print(fb,2,kb,k);print(fb,3,kb,k);print(fc,4,kc,k);
    }
}


方法二参考代码

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<ctime>
#include<cstdlib>
#include<iomanip>
#include<utility>
#define pb push_back
#define mp make_pair
#define CLR(x) memset(x,0,sizeof(x))
#define _CLR(x) memset(x,-1,sizeof(x))
#define REP(i,n) for(int i=0;i<n;i++)
#define Debug(x) cout<<#x<<"="<<x<<" "<<endl
#define REP(i,l,r) for(int i=l;i<=r;i++)
#define rep(i,l,r) for(int i=l;i<r;i++)
#define RREP(i,l,r) for(int i=l;i>=r;i--)
#define rrep(i,l,r) for(int i=1;i>r;i--)
#define read(x) scanf("%d",&x)
#define put(x) printf("%d\n",x)
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<11
using namespace std;

char str1[50],str2[50];
char a[50],b[50],c[50];
int solve(char a[])
{
    int k=50;
    while(k>=0&&a[k]==0) k--;
    while(k>=0)
    {
        if(a[k]>=1)
        {
            while(k-1>=0&&(a[k-1]>=1&&a[k]>=1))
            {
                a[k+1]++,a[k]--,a[k-1]--;
                if(a[k]==0)
                {
                    k--;
                    break;
                }
                else if(a[k-1]==0)
                {
                    k-=2;
                    break;
                }
            }
            if(k-1>=0&&a[k-1]==0)
            {
                while(a[k]>=2)
                {
                    if(k>1)
                        a[k]-=2,a[k+1]++,a[k-2]++;
                    else if(k==1)
                        a[k]-=2,a[k+1]++,a[k-1]++;
                    else
                    {
                        k--;
                        break;
                    }
                }
                k--;
            }
            else if(k>=0) k--;
        }
        else k--;
    }
    k=0;
    while(k<50&&a[k]==0) k++;
    if(k==0)
    {
        while(a[0]>=2)
        {
            a[1]++;
            a[0]-=2;
        }
    }
    while(k<50)
    {
        if(a[k]>=1)
        {
            while(k+1<50&&(a[k+1]>=1&&a[k]>=1))
            {
                a[k+2]++,a[k]--,a[k+1]--;
                if(a[k]==0)
                {
                    k++;
                    break;
                }
                else if(a[k+1]==0)
                {
                    k+=2;
                    break;
                }
            }
            if(k+1<=50&&a[k+1]==0)
            {
                while(a[k]>=2)
                {
                    if(k>1)
                        a[k]-=2,a[k+1]++,a[k-2]++;
                    else if(k==1)
                        a[k]-=2,a[k+1]++,a[k-1]++;
                    else
                    {
                        k++;
                        break;
                    }
                }
                k++;
            }
            else if(k+1>50) k++;
        }
        else k++;
    }
    k=50;
    while(k>=0&&a[k]==0) k--;
    return k;
}

void print(int ka,int shu,int num)
{
    if(num==1) printf("  ");
    if(num==2) printf("+ ");
    if(ka>=0)
    {
        for(int i=0; i<shu-ka; i++)
            printf(" ");
        for(int i=ka; i>=0; i--)
        {
            if(num==1)
                printf("%d",a[i]);
            else if(num==2)
                printf("%d",b[i]);
        }
    }
    else
    {
        for(int i=0; i<shu; i++)
            printf(" ");
        printf("0");
    }
    printf("\n");
}

void print1(int k,int shu)
{
    printf("  ");
    if(shu>=0)
    {
        for(int i=shu; i>=0; i--)
        {
            if(k==1) printf("-");
            else printf("%d",c[i]);
        }
    }
    else
    {
        if(k==1) printf("-");
        else printf("0");
    }
    printf("\n");
    if(k==2) printf("\n");
}

int main()
{
    while(~scanf("%s%s",str1,str2))
    {
        CLR(a);CLR(b);CLR(c);
        int k1=strlen(str1),k2=strlen(str2);
        for(int i=0; i<k1; i++)
            a[i]=str1[k1-1-i]-'0';
        for(int i=0; i<k2; i++)
            b[i]=str2[k2-1-i]-'0';
        int ka=solve(a);
        int kb=solve(b);
        for(int i=50; i>=0; i--)
            c[i]=a[i]+b[i];
        int kc=solve(c);
        int shu=max(max(ka,kb),kc);
        print(ka,shu,1);print(kb,shu,2);print1(1,shu);print1(2,shu);
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: