首页 > 代码库 > bzoj 1002 [FJOI2007]轮状病毒 高精度&&找规律&&基尔霍夫矩阵

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/*15=5*1*116=4*445=5*3*3121=11*11320=5*8*8841=29*292205=5*21*215776=76*7615125396011036802714417106451860496487084512752041*/   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]<<"\t";                }                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 10000class 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!\n->void operator -=(number &num)\n";                        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!\n->void operator --(int)\n";                        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\n");                return 0;        }        if (n==2)        {                printf("5\n");                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;}