bzoj 1002 [FJOI2007]轮状病毒 找规律/基尔霍夫矩阵

                                            bzoj 1002 轮状病毒

Description

给定n(N<=100),编程计算有多少个不同的n轮状病毒。

Input

第一行有1个正整数n。

Output

将编程计算出的不同的n轮状病毒数输出

Sample Input

3

Sample Output

16




      这是道递推的题,难点在于找规律,需要用到基尔霍夫矩阵

通过基尔霍夫矩阵(生成树的计数)得出F(n) = 3 * F(n - 1) - F(n - 2) + 2,其中F(1) = 1, F(2) = 5;

高精度+递推


#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<vector>

using namespace std;

typedef long long ll;
struct Bignum{
static const int BASE=100000000;
static const int MIDTH=8;
vector<int >s;
Bignum (int num=0){*this=num;}
Bignum operator =(int num)
{
    int num1=num;
    if(num1!=0)
    {
    s.clear();
    while(num1>0)
    {
       s.push_back(num1%BASE);
       num1/=MIDTH;
    }
    }
    else s.push_back(0);
    return *this;
}

Bignum operator =(const string num)
{
   s.clear();
   int x,len=(num.length()-1)/MIDTH+1;
    for(int i=0;i<len;i++)
    {
     int end=num.length()-i*MIDTH;
    int start=max(0,end-MIDTH);
     sscanf(num.substr(start,end-start).c_str(),"%d",&x);
     s.push_back(x);
    }
    return *this;
}
Bignum operator +(const Bignum &b)const
{
    Bignum t;
    t.s.clear();
     for(int i=0,g=0;;i++)
     {
         if(g==0&&i>s.size()&&i>b.s.size())
            break;
         int x=g;
         if(i<s.size())
         x+=s[i];
            if(i<b.s.size())
            x+=b.s[i];
       t.s.push_back(x%BASE);
       g=x/BASE;
     }
     return t;
}
Bignum operator -(const Bignum &b)const
    {
        Bignum t;Bignum th=*this;
        t.s.clear();
        for(int i=0,x;; i++)
        {
            if(i>=th.s.size())break;
            if(i<=th.s.size()&&i>=b.s.size())
            {
                x=s[i];
            }
            else
            {
                if(th.s[i]<b.s[i])  th.s[i]+=BASE,th.s[i+1]=s[i+1]-1;
                x=th.s[i]-b.s[i];
            }
            t.s.push_back(x);
        }
        return t;
    }
 Bignum operator *(const int num)const
 {
      Bignum t;
      t.s.clear();
      for(int i=0,g=0;;i++)
      {
        if(g==0&&i>s.size())  break;
         int x=g;
         x+=g;
         x+=num*s[i];
         t.s.push_back(x%BASE);
         g=x/BASE;
      }
      return t;
 }


};
ostream& operator <<(ostream &out,Bignum &b)
{
    while(b.s.back()==0)
    {
        b.s.pop_back();
    }
    char bf[20];

    sprintf(bf,"%08d",b.s.back());
    int j=0;
    while(bf[j]=='0')
    {
        j++;
    }
    for(int i=j; i<strlen(bf); i++)
        out<<bf[i];
    for(int i=b.s.size()-2; i>=0; i--)
    {
        char buf[20];
        sprintf(buf,"%08d",b.s[i]);
        for(int j=0; j<strlen(buf); j++)
            out<<buf[j];
    }
    return out;
}
istream& operator >>(istream &in ,Bignum &b)
{
    string x;
    if(!(in>>x))return in;
    b=x;
    return in;

}
Bignum f[101];
int n;
int main()
{
 scanf("%d",&n);
    f[1]=1;f[2]=5;
   Bignum d=2;
   for(int i=3;i<=n;i++)
   {
       Bignum t=f[i-1]+f[i-1];
       t=t+f[i-1];
       t=t-f[i-2];
       f[i]=t+d;
   }
   cout<<f[n];


   return 0;


}






    


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值