bzoj1002 [FJOI2007]轮状病毒——找规律+高精度

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1002

打表找规律,似乎是这样:https://blog.csdn.net/fzhvampire/article/details/46389897

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n;
struct N{
    int a[50005];
    N(){memset(a,0,sizeof a);}
}f[105],ans;
N add(N x,N y)
{
    N ret;
    ret.a[0]=max(x.a[0],y.a[0]);
    for(int i=1;i<=ret.a[0];i++)
        ret.a[i]=x.a[i]+y.a[i];
    for(int i=1;i<=ret.a[0];i++)
    {
        int t=ret.a[i]/10; ret.a[i]%=10;
        ret.a[i+1]+=t;
    }
    if(ret.a[ret.a[0]+1])ret.a[0]++;
    return ret;
}
N pw(N x)
{
    N ret;
    ret.a[0]=2*x.a[0];
    for(int i=1;i<=x.a[0];i++)
        for(int j=1;j<=x.a[0];j++)
            ret.a[i+j-1]+=x.a[i]*x.a[j];
    for(int i=1;i<=ret.a[0];i++)
    {
        int t=ret.a[i]/10; ret.a[i]%=10;
        ret.a[i+1]+=t;
    }
    if(ret.a[ret.a[0]+1])ret.a[0]++;
    while(ret.a[ret.a[0]]==0&&ret.a[0])ret.a[0]--;
    return ret;
}
void sub(int k)
{
    ans.a[1]-=k; int i=1;
    while(ans.a[i]<0)ans.a[i]+=10,ans.a[++i]--;
    while(ans.a[ans.a[0]]==0&&ans.a[0])ans.a[0]--;
}
void print()
{
    for(int i=ans.a[0];i;i--)printf("%d",ans.a[i]);
}
int main()
{
    scanf("%d",&n);
    f[1].a[0]=1; f[1].a[1]=1;
    f[2].a[0]=1; f[2].a[1]=3;
    for(int i=3;i<=n;i++)
        f[i]=add(f[i-1],f[i-2]);
    ans=pw(f[n]);
    if(n%2==0)sub(4);
    print();
    return 0;
}

还有大家都在说的结论:http://vfleaking.blog.163.com/blog/static/17480763420119685112649/

也就是:f[i] = ( f[i-1]*3 - f[i-2] + 2 )

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n;
struct N{
    int a[50005];
//    N(){memset(a,0,sizeof a);}
}f[105],ans;
N sub(N x,N y)
{
    x.a[1]+=2;
    int j=1;
    while(x.a[j]>=10){x.a[j]%=10;x.a[j+1]++;j++;} 
    for(int i=1;i<=x.a[0];i++)
    {
        x.a[i]-=y.a[i];
        if(x.a[i]<0)x.a[i]+=10,x.a[i+1]--;
    }
//    for(int i=1;i<=x.a[0];i++)
//        if(x.a[i]<0)x.a[i]+=10,x.a[i+1]--;
    while(x.a[x.a[0]]==0&&x.a[0])x.a[0]--;
    return x;
}
//N add(N x,int k)
//{
//    x.a[1]+=k; int i=1;
//    while(x.a[i]>=10)x.a[i+1]+=x.a[i]/10,x.a[i]%=10,i++;
//    if(x.a[x.a[0]+1])x.a[0]++;
//    return x;
//}
N mul(N x,int k)
{
    for(int i=1;i<=x.a[0];i++)x.a[i]*=k;
    for(int i=1;i<=x.a[0];i++)
    {
        x.a[i+1]+=x.a[i]/10; x.a[i]%=10;
    }
    if(x.a[x.a[0]+1])x.a[0]++;
    return x;
}
void print()
{
    for(int i=f[n].a[0];i;i--)printf("%d",f[n].a[i]);
}
int main()
{
    scanf("%d",&n);
    f[1].a[0]=1; f[1].a[1]=1;
    f[2].a[0]=1; f[2].a[1]=5;
    for(int i=3;i<=n;i++)
    {
//        f[i]=mul(f[i-1],3);
//        f[i]=sub(f[i],f[i-2]);
//        f[i]=add(f[i],2);
        f[i]=sub(mul(f[i-1],3),f[i-2]);
    }
    print();
    return 0;
}

果然考场上还是打表找规律比较靠谱...

然而为什么,我的代码跑得好慢...

posted @ 2018-07-02 11:00  Zinn  阅读(225)  评论(0编辑  收藏  举报