bzoj 1002 [FJOI2007]轮状病毒 高精度&&找规律&&基尔霍夫矩阵

1002: [FJOI2007]轮状病毒

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 2234  Solved: 1227
[Submit][Status]

Description

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

Input

第一行有1个正整数n。

Output

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

Sample Input

3

Sample Output

16

HINT

Source

基尔霍夫矩阵总算编出来了,这道题考察的就是数列找规律,要善于联系斐波那契等数列,完全平方数列,奇偶项分别探究。

另外,终于知道c++中四射五入时roundf(float) round(double) roundl(long double)

这道题真在考场上估计是想不出来,主要是因为数列前两项与基尔霍夫矩阵求出的不同,就老是有求错的心理压力。

高精度模板有较小的改动

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
#define eps 1e-7
#define MAXN 111
#ifdef unix120G
#define LL "%lld"
#else 
#define LL "%I64d"
#endif
/*
1
5=5*1*1
16=4*4
45=5*3*3
121=11*11
320=5*8*8
841=29*29
2205=5*21*21
5776=76*76
15125
39601
103680
271441
710645
1860496
4870845
12752041
*/   
typedef long double real;
typedef long long qword;
int n,m,mod;
int a[MAXN][MAXN];
typedef int arr_t[MAXN][MAXN];
real b[MAXN][MAXN];
void pm()
{
        int i,j;
        cout<<endl;
        for (i=0;i<n;i++)
        {
                for (j=0;j<n;j++)
                {
                        cout<<b[i][j]<<"	";
                }
                cout<<endl;
        }
        cout<<endl;
        return ;
}
int gauss(arr_t a,int n)
{
        int i,j,k,sign,x;
        for (i=0;i<n;i++)
        {
                for (j=0;j<n;j++)
                {
                        b[i][j]=a[i][j];
                }
        }
        real temp,ans=1;
        for (i=0;i<n;i++)
        {
                if (abs(b[i][i])<eps)
                {
                        for (j=i+1;j<n;j++)
                        {
                                if (abs(b[j][i])>eps)
                                        break;
                        }
                        if (j==n)return 0;
                        x=j;
                        for (j=0;j<n;j++)
                        {
                                swap(b[x][j],b[i][j]);
                        }
                }
                ans*=b[i][i];
                for (j=i+1;j<n;j++)
                {
                        b[i][j]/=b[i][i];
                }
                for (j=i+1;j<n;j++)
                {
                        for (k=i+1;k<n;k++)
                        {
                                b[j][k]-=b[i][k]*b[j][i];
                        }
                }
        //        pm();
        }
        return (int)roundl(ans);
}

qword work1()
{
        int i,j,k;
        memset(a,0,sizeof(a));
        for (i=0;i<n;i++)
        {
                a[i][(i+1)%n]=a[(i+1)%n][i]=-1;
                a[n][i]=a[i][n]=-1;
        }
        for (i=0;i<n;i++)a[i][i]=3;
        a[n][n]=n;
        cout<<gauss(a,n)<<endl;;
}
#define MAXL 10000
#define VAL1 10000
class number//四位
{
        public:
                number()
                {
                        clear();
                }
                bool is_odd()
                {
                        return numb[0]%2==1;
                }
                bool is_even()
                {
                        return numb[0]%2==0;
                }
                void lsh_bin()
                {
                        int i;
                        for (i=topn;i>0;i--)
                        {
                                if (numb[i]%2==1)
                                {
                                        numb[i-1]+=VAL1;
                                }
                                numb[i]/=2;
                        }
                        numb[0]/=2;
                        while (topn&&!numb[topn])topn--;
                }
                bool equal_to(int x)
                {
                        if (topn==0)
                        {
                                return x==numb[0];
                        }
                        if (topn==1)
                        {
                                return x==numb[0]+numb[1]*VAL1;
                        }
                        return false;
                }
                int size()
                {
                        return topn;
                }
                int length()
                {
                        int x=numb[topn];
                        int ret=0;
                        while (x)
                        {
                                ret++;
                                x/=10;
                        }
                        int y=0;
                        x=VAL1;
                        while (x)
                        {
                                y++;
                                x/=10;
                        }
                        y--;
                        ret+=topn*y;
                        return ret;
                }
                void operator =(int x)//{{{
                {
                        int now=0;
                        clear();
                        numb[now]=x;
                        while (numb[now]>=VAL1)
                        {
                                numb[now+1]+=numb[now]/VAL1;
                                numb[now]%=VAL1;
                                now++;
                                if (now>topn)topn=now;
                        }
                }//}}}
                void operator =(number num)//{{{
                {
                        topn=num.topn;
                        memcpy((this->numb),num.numb,sizeof(num.numb[0])*(topn+1));
                }//}}}
                void operator +=(number &num)//{{{
                {
                        int i;
                        topn=max(topn,num.topn);
                        for (i=0;i<=topn;i++)
                        {
                                numb[i]+=num.numb[i];;
                                if (numb[i]>=VAL1)
                                {
                                        numb[i+1]+=numb[i]/VAL1;
                                        numb[i]%=VAL1;
                                }
                        }
                        while (numb[topn+1])
                        {
                                topn++;
                                numb[topn+1]+=numb[topn]/VAL1;
                                numb[topn]%=VAL1;
                        }
                }//}}}
                void operator +=(int x)//{{{
                {
                        int now=0;
                        if (topn==-1)topn=0;
                        numb[now]+=x;
                        while (numb[now]>=VAL1)
                        {
                                numb[now+1]+=numb[now]/VAL1;
                                numb[now]%=VAL1;
                                now++;
                                if (now>topn)topn=now;
                        }
                }//}}}
                void operator *=(int x)//{{{
                {
                        int i;
                        for (i=0;i<=topn;i++)
                        {
                                numb[i]*=x;
                        }
                        for (i=0;i<=topn;i++)
                        {
                                if (numb[i]>=VAL1)
                                {
                                        numb[i+1]+=numb[i]/VAL1;
                                        numb[i]%=VAL1;
                                }
                        }
                        while (numb[topn+1])
                        {
                                topn++;
                                numb[topn+1]+=numb[topn]/VAL1;
                                numb[topn]%=VAL1;
                        }
                }//}}}
                void operator -=(number &num)//{{{
                {
                        if (*this<num)throw "Error!
->void operator -=(number &num)
";
                        int i;
                        for (i=0;i<=topn;i++)
                        {
                                numb[i]-=num.numb[i];
                        }
                        for (i=0;i<=topn;i++)
                        {
                                while (numb[i]<0)
                                {
                                        numb[i]+=VAL1;
                                        numb[i+1]--;
                                }
                        }
                        while (topn&&!numb[topn])topn--;
                }//}}}
                void operator --(int)//{{{
                {
                        if (topn==0&&numb[0]==0)throw "Error!
->void operator --(int)
";
                        int now=0;
                        numb[now]--;
                        while (numb[now]<0)
                        {
                                numb[now+1]--;
                                numb[now]+=VAL1;
                        }
                        while (topn&&!numb[topn])topn--;
                }//}}}
        private:
                int numb[MAXL];
                int topn;
                void clear()
                {
                        topn=0;
                        memset(numb,0,sizeof(numb));

                }
                friend bool operator <(number num1,number num2);
                friend bool operator <=(number num1,number num2);
                friend bool operator ==(number num1,number num2);
                friend ostream& operator <<(ostream &out,number &num);
                friend istream& operator >>(istream &in,number &num);
                friend number operator *(number &num1,number &num2);
                friend number operator *(number num,int x);
                friend number operator +(number num1,number num2);
                friend number operator +(number num1,int x);
                friend number operator -(number num1,number num2);
                //a=a+b远没有a+=b快
};
bool operator <(number num1,number num2)//{{{
{
        if (num1.topn!=num2.topn)
        {
                return num1.topn<num2.topn;
        } 
        int i;
        for (i=num1.topn;i>=0;i--)
        {
                if (num1.numb[i]!=num2.numb[i])
                {
                        return num1.numb[i]<num2.numb[i];
                }
        }
        return false;
}//}}}
bool operator <=(number num1,number num2)//{{{
{
        if (num1.topn!=num2.topn)
        {
                return num1.topn<num2.topn;
        } 
        int i;
        for (i=num1.topn;i>=0;i--)
        {
                if (num1.numb[i]!=num2.numb[i])
                {
                        return num1.numb[i]<num2.numb[i];
                }
        }
        return true;
}//}}}
bool operator ==(number num1,number num2)//{{{
{
        if (num1.topn!=num2.topn)return false;
        for (int i=0;i<=num1.topn;i++)
        {
                if (num1.numb[i]!=num2.numb[i])return false;
        }
        return true;
}//}}}
ostream& operator <<(ostream &out,number &num)//{{{
{
        int i;
        out<<num.numb[num.topn];
        for (i=num.topn-1;i>=0;i--)
        {
                //压六位时
        //        if (num.numb[i]<100000)out<<"0";
        //        if (num.numb[i]<10000)out<<"0";
                if (num.numb[i]<1000)out<<"0";
                if (num.numb[i]<100)out<<"0";
                if (num.numb[i]<10)out<<"0";
                out<<num.numb[i];
        }
        return out;
}//}}}
istream& operator >>(istream &in,number &num)//{{{
{
        string str;
        in>>str;
        int i;
        num.clear();
        for (i=(int)str.length()-1,num.topn=0;i>=0;i-=4,num.topn++)
        {
                if (i-3<str.length())
                {
                        num.numb[num.topn]=(str[i]-'0')+10*(str[i-1]-'0')+100*(str[i-2]-'0')+1000*(str[i-3]-'0');
                }else
                {
                        if (i-2<str.length())num.numb[num.topn]+=100*(str[i-2]-'0');
                        if (i-1<str.length())num.numb[num.topn]+=10*(str[i-1]-'0');
                        if (i  <str.length())num.numb[num.topn]+=(str[i]-'0');
                }
        }
        num.topn--;
        return in;
}//}}}
number operator *(number num,int x)//{{{
{
        number ret;
        ret=num;
        ret*=x;
        return ret;
}//}}}
number operator +(number num1,number num2)//{{{
{
        number ret;
        ret=num1;
        ret+=num2;
        return ret;
}//}}}
number operator +(number num1,int x)//{{{
{
        number ret;
        ret=num1;
        ret+=x;
        return ret;
}//}}}
number operator -(number num1,number num2)//{{{
{
        number ret;
        ret=num1;
        ret-=num2;
        return ret;
}//}}
number f[101];
int main()
{
        freopen("input.txt","r",stdin);
        //freopen(PROB".out","w",stdout);
        int x,y;
        int i,j,k;
        scanf("%d",&n);
        if (n==1)
        {
                printf("1
");
                return 0;
        }
        if (n==2)
        {
                printf("5
");
                return 0;
        }
        f[1]=1;f[2]=5;
        for (i=3;i<=n;i++)
                f[i]=f[i-1]*3-f[i-2]+2;
        //for (i=1;i<=n;i++)cout<<f[i]<<endl;
        cout<<f[n]<<endl;
        return 0;
}
by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

本博客已停用,新博客地址:http://mhy12345.xyz

原文地址:https://www.cnblogs.com/mhy12345/p/3834807.html