楼天城之做男人就过八道题(第一题…

关于楼教主的第一题,感觉最费时间的还是高精度的实现 。实现一万位以上整数基本运算的 万进制高精度 模版就写了快一天(题目里用到大概也有几百位吧) ,只能说太容易出错了,得不断地调试修改。 题目源地址是北大poj1737 题, 题目本身的组合数学的算法是参考某位大牛的文章,在此附上地址 http://hi.baidu.com/accplaystation/item/0b3b4e1654a07548e75e06f9  
下面分别是49和50个点时的结果以及源代码,供参考:
49:
10263013515700550779116289728670421776807355856352253452035361907379108631238572
445483139828762289949878 647004007598114562441288 897543063864595578874322 98148719
591734971030611474690885 904247396313959818854940 592795291449937598794070 51757016
755160795097926623799779 728356364524210524473752 088137141096006790217662 98295142
562256412381640145736443 33472284672

50:
577756298062641319815321 284633539861082132919998 722885657507672188606317 69630192
413406823351870787784176 925235627483488367832092 229178528895225932496008 59338855
724814764410440416662456 329476306676699006233890 696555233449522221141796 60086674
251300523449279256078271 770682664276058349275922 600493471476178420154378 01204857
133343656736539713615246 916548098015836904200601 6

 

#include "iostream"
#include "string"
#include "cstring"
#include "stdio.h"

using namespace std;

bool remember[55];

struct bigNumber
{
    int num[100];
    int ans;
    bigNumber()
    {
        memset(num,0,sizeof(num));
        ans=1;
    }
    bigNumber operator =(int k)
    {
    int i=0;
    num[i]=k000;
    while(k>=10000)
    {
        i++;
        k/=10000;
        num[i]=k000;
    }
    ans=i+1;
    return *this;
    }
};

bigNumber number[55];
bigNumber bigNumber1,bigNumber2,bigNumber3;

ostream& operator << (ostream& os, constbigNumber& big)//输出高精度数运算符重载
{
    os<<big.num[big.ans-1];
    for(inti=big.ans-2;i>=0;i--)
    {
        if(big.num[i]==0)
            os<<"000";
        else if(big.num[i]<10)
            os<<"000";
        else if(big.num[i]<100)
            os<<"00";
        else if(big.num[i]<1000)
            os<<"0";
        os<<big.num[i];
    }
    return os;
}

istream& operator>>(istream& is, bigNumber &big)//输入高精度运算符的重载
{
    string s;
    is>>s;
    intlength=s.size();
    for(int i=0;i
    {
        char a=s[i];
        s[i]=s[length-1-i];
        s[length-1-i]=a;
    }
    int m=1;
    for(int i=0;i
    {
        int a=s[i]-'0';
        big.num[i/4]+=a*m;
        m*=10;
        if(m==10000)
            m=1;
    }
    big.ans=(length-1)/4+1;
    return is;
}

bigNumber operator*(bigNumber big1,bigNumberbig2)//两个高精度数相乘
{
    bigNumber big3;
    for(int i=0;i
    {
        for(int j=0;j
        {
          inta=big1.num[i]*big2.num[j];
          big3.num[i+j]+=a000;
          big3.num[i+j+1]+=a/10000;
        }
        for(int k=i;k<=i+big2.ans;k++)
        {
            if(big3.num[k]>=10000)
            {
                big3.num[k+1]+=big3.num[k]/10000;
                big3.num[k]=big3.num[k]000;
            }
        }
    }
    big3.ans=big1.ans+big2.ans;
    while(big3.num[big3.ans]==0)
        big3.ans--;
      big3.ans++;
      if(big3.ans==0)
        big3.ans++;
      returnbig3;
}

bigNumber operator*(bigNumber big,intk)//高精度乘以普通常数(注意常数的大小范围不可太大)
{
    bigNumber tool;
    for(int i=0;i
    {
        int product=big.num[i]*k;
        tool.num[i]+=product000;
        int j=i;
        while(product>=10000)
        {
            product/=10000;
          tool.num[++j]+=product000;
        }
    }
    tool.ans=big.ans+10;
    while(tool.num[tool.ans]==0)
        tool.ans--;
    tool.ans++;
    big=tool;
    return big;
}

bigNumber operator+(bigNumber big1,bigNumberbig2)//两个高精度数相加,将和赋在第一个数上
{
      bigNumber tool=big1;
    for(int i=0;i
    {
        tool.num[i]+=big2.num[i];
        int j=i;
        while(tool.num[j]>=10000)
        {
            inta=tool.num[j];
            tool.num[j]=a000;
            tool.num[j+1]+=a/10000;
            j++;
        }
    }
    tool.ans=max(big1.ans+1,big2.ans+1);
    while(tool.num[tool.ans]==0)
        tool.ans--;
    tool.ans++;
    return tool;
}
bigNumber operator/(bigNumber &big1,int k)
{
    int i=big1.ans-1;
    int a;
    while(i>=0)
    {
        a=big1.num[i];
        big1.num[i]=0;
    while(i>0&&a
    {
        a*=10000;
        a+=big1.num[--i];
        big1.num[i]=0;
    }
    big1.num[i]=a/k;
    if(i==0)
        break;
    if(i>0)
        big1.num[--i]+=(a%k)*10000;

    }
    while(big1.num[big1.ans]==0)
        big1.ans--;
    big1.ans++;
    return big1;
}

bigNumber function0(int n)
{
    if(n==1||n==2)
    {
        bigNumber big;
        big.num[0]=1;
        return big;
    }
    if(remember[n])
        return number[n];
    bigNumber tool;
    for(int k=1;k
    {
        bigNumber big1=function0(k);
        bigNumber big2=function0(n-k);
        bigNumber big3;
        big3.num[0]=1;
        for(int i=n-2;i>n-2-k+1;i--)
        {
            big3=big3*i;
        }
        for(int i=2;i<=k-1;i++)
            big3=big3/i;
        bigNumber big4;
        big4.num[0]=1;
        for(int i=1;i<=k;i++)
            big4=big4*2;
            big4.num[0]-=1;
        tool=tool+(big1*big2*big3*big4);
    }
    remember[n]=true;
    number[n]=tool;
    return tool;
}



int main()
{
    for(inti=0;i<=50;i++)
    remember[i]=false;
    int n;
    while(scanf("%d",&n)!=EOF&&n!=0)
    cout<<function0(n)<<endl;;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值