zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    [CentOS_7.4]Linux编译安装mono环境
    [CentOS_7.4]Linux安装与网络配置
    div框选中状态,倒三角样式
    photoswipe图片滑动插件使用
    微信应用号(小程序)开发教程二
    微信应用号(小程序)开发教程一
    开发者必去的10大国内网站推荐
    愤怒的小鸟 高清完整版下载
    魔兽 高清完整版下载
    分歧者3 高清完整版下载
  • 原文地址:https://www.cnblogs.com/mhy12345/p/3834807.html
Copyright © 2011-2022 走看看