• BZOJ 1002 轮状病毒 矩阵树定理


    题目链接:

    https://www.lydsy.com/JudgeOnline/problem.php?id=1002

    题目大意:

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

    思路:

    大部分题解都是直接一个递推公式,具体得来的方法由矩阵树定理可以求得。

    只是求矩阵的行列式的时候比较复杂。

    具体证明过程:http://vfleaking.blog.163.com/blog/static/17480763420119685112649/

    需要高精度

      1 #include <bits/stdc++.h>
      2 #define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
      3 #define Max(a, b) (a) > (b) ? (a) : (b)
      4 #define Min(a, b) (a) < (b) ? (a) : (b)
      5 #pragma comment(linker, "/STACK:102400000,102400000")
      6 using namespace std;
      7 
      8 typedef long long ll;
      9 const int mod = 1e9 + 7;
     10 const int maxn = 1000000 + 10;
     11 
     12 #define MAXN 9999
     13 #define MAXSIZE 1000
     14 #define DLEN 4
     15 //如果位数特别大,可以把数组a放大,也可以把MAXN多加几个9,同时DLEN = 9的个数 后者方法会更快
     16 class BigNum {
     17 private:
     18 public:
     19     ll a[1000];    //可以控制大数的位数
     20     int len;        //大数长度
     21 
     22     BigNum() {len = 1;memset(a,0,sizeof(a));}   //构造函数
     23     BigNum(const ll);      //int 构造函数
     24     BigNum(const char*);    //字符串 构造函数
     25     BigNum(const string);   //string 构造函数
     26     BigNum(const BigNum &); //拷贝构造函数
     27     BigNum &operator=(const BigNum &);//重载赋值运算符
     28 
     29     friend istream& operator >> (istream&, BigNum&);//重载输入运算符
     30     friend ostream& operator << (ostream&, BigNum&);//重载输出运算符
     31 
     32     BigNum operator + (const BigNum &) const;//重载加法
     33     BigNum operator - (const BigNum &) const;//重载减法
     34     BigNum operator * (const BigNum &) const;//重载乘法
     35     BigNum operator / (const ll &) const;   //重载除法 int
     36     BigNum operator ^ (const ll &) const;   //n次方
     37     ll operator % (const ll &) const;      //对int 取模
     38 
     39     bool operator > (const BigNum & T)const; //比较大小
     40     bool operator > (const ll & t)const;
     41     bool operator < (const BigNum & T)const;
     42     bool operator < (const ll & t)const;
     43     bool operator == (const BigNum & T)const;
     44     bool operator == (const ll & t)const;
     45 
     46     void print();   //输出大数
     47 };
     48 BigNum::BigNum(const ll b) //int 构造函数
     49 {
     50     ll c, d = b;
     51     len = 0;
     52     memset(a,0,sizeof(a));
     53     while(d > MAXN)
     54     {
     55         c = d - (d / (MAXN + 1)) * (MAXN + 1);
     56         d = d / (MAXN + 1); a[len++] = c;
     57     }
     58     a[len++] = d;
     59 }
     60 BigNum::BigNum(const char*s)//字符串 构造函数
     61 {
     62     ll t, k, index, l;
     63     memset(a,0,sizeof(a));
     64     l = strlen(s);
     65     len = l / DLEN;
     66     if(l % DLEN)len++;
     67     index=0;
     68     for(int i = l - 1; i >= 0;i -= DLEN)
     69     {
     70         t = 0; k = i - DLEN + 1;
     71         if(k < 0)k = 0;
     72         for(int j = k; j <= i; j++)
     73             t = t * 10 + s[j] - '0';
     74         a[index++]=t;
     75     }
     76 }
     77 BigNum::BigNum(const string s)//字符串 构造函数
     78 {
     79     ll t, k, index, l;
     80     memset(a,0,sizeof(a));
     81     l = s.size();
     82     len = l / DLEN;
     83     if(l % DLEN)len++;
     84     index=0;
     85     for(int i = l - 1; i >= 0;i -= DLEN)
     86     {
     87         t = 0; k = i - DLEN + 1;
     88         if(k < 0)k = 0;
     89         for(int j = k; j <= i; j++)
     90             t = t * 10 + s[j] - '0';
     91         a[index++]=t;
     92     }
     93 }
     94 BigNum::BigNum(const BigNum & T) : len(T.len)//拷贝构造函数
     95 {
     96     memset(a,0,sizeof(a));
     97     for(int i = 0 ; i < len ; i++)a[i] = T.a[i];
     98 }
     99 BigNum & BigNum::operator = (const BigNum & n)//重载赋值运算符
    100 {
    101     len = n.len;
    102     memset(a,0,sizeof(a));
    103     for(int i = 0 ; i < len ; i++)
    104         a[i] = n.a[i];
    105     return *this;
    106 }
    107 istream& operator >> (istream & in, BigNum & b)//重载输入运算符
    108 {
    109     char ch[MAXSIZE * 4];
    110     in >> ch;
    111     int l = strlen(ch);
    112     ll count = 0, sum = 0;
    113     for(int i = l - 1; i >= 0;)
    114     {
    115         sum = 0;
    116         ll t = 1;
    117         for(int j = 0; j < DLEN && i >= 0; j++, i--, t *= 10)
    118             sum += (ch[i] - '0') * t;
    119         b.a[count] = sum;
    120         count++;
    121     }
    122     b.len = count++;
    123     return in;
    124 }
    125 ostream& operator << (ostream& out, BigNum& b)//重载输出运算符
    126 {
    127     cout<<b.a[b.len - 1];
    128     for(int i = b.len - 2; i >= 0; i--)
    129     {
    130         cout.width(DLEN);
    131         cout.fill('0');
    132         cout<<b.a[i];
    133     }
    134     return out;
    135 }
    136 BigNum BigNum::operator + (const BigNum & T) const //重载加法
    137 {
    138     BigNum t(*this);
    139     ll i,big;//位数
    140     big = T.len > len ? T.len : len;
    141     for(i = 0 ; i < big ; i++)
    142     {
    143         t.a[i] +=T.a[i];
    144         if(t.a[i] > MAXN)
    145         {
    146             t.a[i + 1]++;
    147             t.a[i] -= MAXN + 1;
    148         }
    149     }
    150     if(t.a[big] != 0) t.len = big + 1;
    151     else t.len = big;
    152     return t;
    153 }
    154 BigNum BigNum::operator - (const BigNum & T) const //重载减法
    155 {
    156     ll i,j,big;
    157     bool flag;
    158     BigNum t1,t2;
    159     if(*this > T)
    160     {
    161         t1 = *this;
    162         t2 = T;
    163         flag = 0;
    164     }
    165     else
    166     {
    167         t1 = T;
    168         t2 = *this;
    169         flag = 1;
    170     }
    171     big = t1.len;
    172     for(i = 0 ; i < big ; i++)
    173     {
    174         if(t1.a[i] < t2.a[i])
    175         {
    176             j = i + 1;
    177             while(t1.a[j] == 0) j++;
    178             t1.a[j--]--;
    179             while(j > i) t1.a[j--] += MAXN;
    180             t1.a[i] += MAXN + 1 - t2.a[i];
    181         }
    182         else t1.a[i] -= t2.a[i];
    183     }
    184     t1.len = big;
    185     while(t1.a[t1.len - 1] == 0 && t1.len > 1)
    186     {
    187         t1.len--;
    188         big--;
    189     }
    190     if(flag)t1.a[big - 1] = 0 - t1.a[big - 1];
    191     return t1;
    192 }
    193 BigNum BigNum::operator * (const BigNum & T) const //重载乘法
    194 {
    195     BigNum ret;
    196     ll i,j,up;
    197     ll temp,temp1;
    198     for(i = 0 ; i < len ; i++)
    199     {
    200         up = 0;
    201         for(j = 0 ; j < T.len ; j++)
    202         {
    203             temp = a[i] * T.a[j] + ret.a[i + j] + up;
    204             if(temp > MAXN)
    205             {
    206                 temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
    207                 up = temp / (MAXN + 1);
    208                 ret.a[i + j] = temp1;
    209             }
    210             else
    211             {
    212                 up = 0;
    213                 ret.a[i + j] = temp;
    214             }
    215         }
    216         if(up != 0)
    217             ret.a[i + j] = up;
    218     }
    219     ret.len = i + j;
    220     while(ret.a[ret.len - 1] == 0 && ret.len > 1) ret.len--;
    221     return ret;
    222 }
    223 BigNum BigNum::operator / (const ll & b) const //重载除法
    224 {
    225     BigNum ret;
    226     ll i,down = 0;
    227     for(i = len - 1 ; i >= 0 ; i--)
    228     {
    229         ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
    230         down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
    231     }
    232     ret.len = len;
    233     while(ret.a[ret.len - 1] == 0 && ret.len > 1) ret.len--;
    234     return ret;
    235 }
    236 ll BigNum::operator % (const ll & b) const //重载取模
    237 {
    238     ll i,d=0;
    239     for (i = len-1; i>=0; i--)
    240     {
    241         d = ((d * (MAXN+1))% b + a[i])% b;
    242     }
    243     return d;
    244 }
    245 BigNum BigNum::operator^(const ll & n) const //重载n次方
    246 {
    247     BigNum t,ret(1);
    248     if(n < 0)exit(-1);
    249     if(n == 0)return 1;
    250     if(n == 1)return *this;
    251     ll m = n;
    252     while(m > 1)
    253     {
    254         t = *this;
    255         ll i;
    256         for(i = 1; i << 1 <= m; i <<= 1)
    257         {
    258             t = t * t;
    259         }
    260         m -= i;
    261         ret = ret * t;
    262         if(m == 1)ret = ret * (*this);
    263     }
    264     return ret;
    265 }
    266 bool BigNum::operator > (const BigNum & T) const //两大整数 大于号重载
    267 {
    268     ll ln;
    269     if(len > T.len) return true;
    270     else if(len == T.len)
    271     {
    272         ln = len - 1;
    273         while(a[ln] == T.a[ln] && ln >= 0) ln--;
    274         if(ln >= 0 && a[ln] > T.a[ln]) return true;
    275         else return false;
    276     }
    277     else return false;
    278 }
    279 bool BigNum::operator > (const ll & t) const
    280 {
    281     return *this > BigNum(t);
    282 }
    283 bool BigNum::operator < (const BigNum & T) const //两大整数 小于号重载
    284 {
    285     return T > *this;
    286 }
    287 bool BigNum::operator < (const ll & t) const
    288 {
    289     return BigNum(t) > *this;
    290 }
    291 bool BigNum::operator == (const BigNum & T) const //两大整数 等于号重载
    292 {
    293     return !(T > *this) && !(*this > T);
    294 }
    295 bool BigNum::operator == (const ll & t) const
    296 {
    297     return BigNum(t) == *this;
    298 }
    299 void BigNum::print()
    300 {
    301     int i;
    302     cout << a[len - 1];
    303     for(i = len - 2 ; i >= 0 ; i--)
    304     {
    305         cout.width(DLEN);
    306         cout.fill('0');
    307         cout << a[i];
    308     }
    309 }
    310 
    311 int main()
    312 {
    313     int n;
    314     cin >> n;
    315     if(n == 1)puts("1");
    316     else if(n == 2)puts("5");
    317     else
    318     {
    319         BigNum a(1), b(5), c;
    320         for(int i = 3; i <= n; i++)
    321         {
    322             c = BigNum(3LL) * b;
    323             c = c - a;
    324             c = c + BigNum(2LL);
    325             a = b;
    326             b = c;
    327         }
    328         cout<<c<<endl;
    329     }
    330     return 0;
    331 }
  • 相关阅读:
    codeblocks基本调试方法—gdb—Debugger
    五大开源Web服务器
    【u237】分数化小数
    【u230】回文词
    【t099】最接近神的人
    【t052】冰岛
    【t069】奇怪的迷宫
    【p092】分数线划定
    【u243】拓扑排序
    【u247】生物进化
  • 原文地址:https://www.cnblogs.com/fzl194/p/9678566.html
Copyright © 2020-2023  润新知