2.4 【高精度】 FJOI2007 轮状病毒

本文介绍了FJOI2007轮状病毒问题的解题思路,通过观察规律发现了一个类斐波那契数列,并使用高精度计算实现了递推求解。适用于对算法竞赛和数列问题感兴趣的读者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

FJOI2007 轮状病毒

传送门:https://www.luogu.org/problemnew/show/P2144

暴力找规律
发现n=1~5时答案是1,5,16,45,121
奇数项是平方数,偶数项是平方数减4
1,5,16,45,121 分别是1^2,3^2-4,4^2,7^2-4,11^2
1,3,4,7,11这个数列有类似于斐波那契数列的性质,只不过前两项是1和3罢了
那么我们就可以递推求这个类斐波那契数列的第n项,然后平方,然后再根据n的奇偶来决定是否减4
高精度代码如下

#include<cstdio> 
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<iostream>
#include<cstdlib>
using namespace std;
class Bigint{
    public:
    int size,num[10000];
    Bigint(){
        size=0;
        memset(num,0,sizeof(num));
    }
    Bigint(int data)
    {
        size=0;
        while(data!=0)
        {
            size++;
            num[size]=data%10;
            data/=10;
        }
    }
    void init(int data)
    {
        size=0;
        while(data!=0)
        {
            size++;
            num[size]=data%10;
            data/=10;
        }
    }
};
Bigint operator + (Bigint A,Bigint B){
    Bigint ans;
    int s=max(A.size,B.size);
    ans.size=s;
    for(int i=1;i<=s;i++)
        ans.num[i]=A.num[i]+B.num[i];
    for(int i=1;i<=s;i++)
        if(ans.num[i]>=10)
        {
            ans.num[i+1]+=ans.num[i]/10;
            ans.num[i]%=10;
        }
    if(ans.num[s+1]!=0)
        ans.size++;
    return ans;
}
Bigint operator - (Bigint A,Bigint B){
    Bigint ans;
    int s=max(A.size,B.size);
    ans.size=s;
    for(int i=1;i<=s;i++)
        ans.num[i]=A.num[i]-B.num[i];
    for(int i=1;i<=s;i++)
        if(ans.num[i]<0)
        {
            ans.num[i+1]--;
            ans.num[i]=(ans.num[i]+10)%10;
        }
    while(ans.num[ans.size]==0)
        ans.size--;
    return ans;
}
Bigint operator * (Bigint A,Bigint B){
    Bigint ans;
    int s1=A.size,s2=B.size;
    for(int i=1;i<=s1;i++)
        for(int j=1;j<=s2;j++)
            ans.num[i+j-1]+=A.num[i]*B.num[j];
    int s=s1+s2-1;
    int k=1;
    while(ans.num[k]!=0||k<=s)
    {
        ans.num[k+1]+=ans.num[k]/10;
        ans.num[k]%=10;
        k++;
    }
    if(ans.num[k]==0)k--;
    ans.size=k;
    return ans;
}
ostream & operator << (ostream &os,Bigint A){
    int s=A.size;
    for(int i=s;i>=1;i--)
        os<<A.num[i];
    return os;
}
Bigint P,Q,ANS;
int n;
int main(){
    cin>>n;
    P.init(1);
    Q.init(3);
    for(int i=3;i<=n;i++)
    {
        if(i%2)P=P+Q;
        else Q=P+Q;
    }
    if(n%2)ANS=P;
    else ANS=Q;
    ANS=ANS*ANS;
    if(n%2==0)ANS=ANS-4;
    cout<<ANS<<endl;
    return 0;
}


LLAP.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值