HDU 4099---字典树+大数加法

http://acm.hdu.edu.cn/showproblem.php?pid=4099

题意很简单,就是让你在字典树上跑大斐波那契………只不过我们不能完全按照他题意的意思做0 0 因为据说10W位的斐波那契数有2W位0……0蛋疼…………因此我们只要把数据控制在前40位就行,但是存储的时候还是要存储前60位这样如果出现了那种奇葩的数 假设第57位和第58位相加后会导致所有位向前进一位…………0^0 想想都烦……所以我干脆把位数存储在第60位即可。

杭电应该是改数据了,这题我曾经MLE了10多次结果这次拿之前代码直接过了 7……7

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#define maxs 1000010
#define MME(i,j) memset(i,j,sizeof(i))
using namespace std;
char FB[3][104];

typedef struct node
{
    struct node *nexts[10];
    int id;
} Trienode,*Trie;

Trie buildNode()
{
    Trie p=new node;
    MME(p->nexts,0);
    p->id=-1;
    return p;
}

void inser(char *s,Trie root,int num)
{
    int i=0,id,len=strlen(s);
    Trie p=root;
    for(int i=0; i<len&&i<41; i++)
    {
        id=s[i]-'0';
        if(p->nexts[id]==NULL)
            p->nexts[id]=buildNode();
        p=p->nexts[id];
        if(p->id<0)
            p->id=num;
    }
    if(p->id<0)
        p->id=num;
    //printf("%d\n",p->id);
}//建树过程

int finds(char *s,Trie root)
{
    int i=0,id;
    while(s[i])
    {
        id=s[i]-'0';
        if(root->nexts[id]==NULL)
            return -1;
        root=root->nexts[id];
        i++;
    }
    return root->id;
}//查询过程

void str_add(char *a,char *b,char *c)//大数加法- -我们只要3个数组就行开多了反而MLE
{
    char temp[200];
    int lena=strlen(a),lenb=strlen(b);

    int a_pos=lena-1,b_pos=lenb-1,idxa,idxb;

    int k=0,jinwei=0;
    while(a_pos>=0||b_pos>=0)
    {
        if(a_pos<0)idxa=0;
        else idxa=a[a_pos]-'0';
        if(b_pos<0)idxb=0;
        else idxb=b[b_pos]-'0';
        int sum=idxa+idxb+jinwei;
        temp[k++]=(sum%10)+'0';
        jinwei=(idxa+idxb+jinwei)/10;
        a_pos--;
        b_pos--;
    }
    if(jinwei)
        temp[k++]=jinwei+'0';
    temp[k]='\0';

    for(int i=0; i<k; i++)
        c[i]=temp[k-1-i];
    c[k]='\0';

    return;
}

void deletetree(Trie root)
{
    for(int i=0; i<10; i++)
    {
        if(root->nexts[i])
            deletetree(root->nexts[i]);
    }
    delete root;
}

int main()
{
    int times=1;
    Trie root=buildNode();
    FB[0][0]='1';
    FB[0][1]='\0';
    inser(FB[0],root,0);
    FB[1][0]='1';
    FB[1][1]='\0';

    int len1,len2;
    for(int i=2; i<100000; i++)
    {
        len1=strlen(FB[0]);
        len2=strlen(FB[1]);// len 2>60 因为虽然我们只要40位但是如果出现了及其特别的数比如后面相加后都可以进一位那么会让最后的结果又差异
        if(len2>60)//因为第10W个 FB数大约有 2W 位,那么运用大数加法会变得特慢
        {
            FB[0][len1-1]=0;
            FB[1][len2-1]=0;
        }
        str_add(FB[0],FB[1],FB[2]);
        inser(FB[2],root,i);
        strcpy(FB[0],FB[1]);
        strcpy(FB[1],FB[2]);
    }//初始化前10W个

    int t;
    while(~scanf("%d",&t))
    {
        int ans;
        while(t--)
        {
            scanf("%s",FB[0]);
            ans=finds(FB[0],root);
            printf("Case #%d: %d\n",times++,ans);
        }
    }
    deletetree(root);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值