题目链接:

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

题目大意:

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

思路:

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

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

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

需要高精度

 #include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
#define Max(a, b) (a) > (b) ? (a) : (b)
#define Min(a, b) (a) < (b) ? (a) : (b)
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std; typedef long long ll;
const int mod = 1e9 + ;
const int maxn = + ; #define MAXN 9999
#define MAXSIZE 1000
#define DLEN 4
//如果位数特别大,可以把数组a放大,也可以把MAXN多加几个9,同时DLEN = 9的个数 后者方法会更快
class BigNum {
private:
public:
ll a[]; //可以控制大数的位数
int len; //大数长度 BigNum() {len = ;memset(a,,sizeof(a));} //构造函数
BigNum(const ll); //int 构造函数
BigNum(const char*); //字符串 构造函数
BigNum(const string); //string 构造函数
BigNum(const BigNum &); //拷贝构造函数
BigNum &operator=(const BigNum &);//重载赋值运算符 friend istream& operator >> (istream&, BigNum&);//重载输入运算符
friend ostream& operator << (ostream&, BigNum&);//重载输出运算符 BigNum operator + (const BigNum &) const;//重载加法
BigNum operator - (const BigNum &) const;//重载减法
BigNum operator * (const BigNum &) const;//重载乘法
BigNum operator / (const ll &) const; //重载除法 int
BigNum operator ^ (const ll &) const; //n次方
ll operator % (const ll &) const; //对int 取模 bool operator > (const BigNum & T)const; //比较大小
bool operator > (const ll & t)const;
bool operator < (const BigNum & T)const;
bool operator < (const ll & t)const;
bool operator == (const BigNum & T)const;
bool operator == (const ll & t)const; void print(); //输出大数
};
BigNum::BigNum(const ll b) //int 构造函数
{
ll c, d = b;
len = ;
memset(a,,sizeof(a));
while(d > MAXN)
{
c = d - (d / (MAXN + )) * (MAXN + );
d = d / (MAXN + ); a[len++] = c;
}
a[len++] = d;
}
BigNum::BigNum(const char*s)//字符串 构造函数
{
ll t, k, index, l;
memset(a,,sizeof(a));
l = strlen(s);
len = l / DLEN;
if(l % DLEN)len++;
index=;
for(int i = l - ; i >= ;i -= DLEN)
{
t = ; k = i - DLEN + ;
if(k < )k = ;
for(int j = k; j <= i; j++)
t = t * + s[j] - '';
a[index++]=t;
}
}
BigNum::BigNum(const string s)//字符串 构造函数
{
ll t, k, index, l;
memset(a,,sizeof(a));
l = s.size();
len = l / DLEN;
if(l % DLEN)len++;
index=;
for(int i = l - ; i >= ;i -= DLEN)
{
t = ; k = i - DLEN + ;
if(k < )k = ;
for(int j = k; j <= i; j++)
t = t * + s[j] - '';
a[index++]=t;
}
}
BigNum::BigNum(const BigNum & T) : len(T.len)//拷贝构造函数
{
memset(a,,sizeof(a));
for(int i = ; i < len ; i++)a[i] = T.a[i];
}
BigNum & BigNum::operator = (const BigNum & n)//重载赋值运算符
{
len = n.len;
memset(a,,sizeof(a));
for(int i = ; i < len ; i++)
a[i] = n.a[i];
return *this;
}
istream& operator >> (istream & in, BigNum & b)//重载输入运算符
{
char ch[MAXSIZE * ];
in >> ch;
int l = strlen(ch);
ll count = , sum = ;
for(int i = l - ; i >= ;)
{
sum = ;
ll t = ;
for(int j = ; j < DLEN && i >= ; j++, i--, t *= )
sum += (ch[i] - '') * t;
b.a[count] = sum;
count++;
}
b.len = count++;
return in;
}
ostream& operator << (ostream& out, BigNum& b)//重载输出运算符
{
cout<<b.a[b.len - ];
for(int i = b.len - ; i >= ; i--)
{
cout.width(DLEN);
cout.fill('');
cout<<b.a[i];
}
return out;
}
BigNum BigNum::operator + (const BigNum & T) const //重载加法
{
BigNum t(*this);
ll i,big;//位数
big = T.len > len ? T.len : len;
for(i = ; i < big ; i++)
{
t.a[i] +=T.a[i];
if(t.a[i] > MAXN)
{
t.a[i + ]++;
t.a[i] -= MAXN + ;
}
}
if(t.a[big] != ) t.len = big + ;
else t.len = big;
return t;
}
BigNum BigNum::operator - (const BigNum & T) const //重载减法
{
ll i,j,big;
bool flag;
BigNum t1,t2;
if(*this > T)
{
t1 = *this;
t2 = T;
flag = ;
}
else
{
t1 = T;
t2 = *this;
flag = ;
}
big = t1.len;
for(i = ; i < big ; i++)
{
if(t1.a[i] < t2.a[i])
{
j = i + ;
while(t1.a[j] == ) j++;
t1.a[j--]--;
while(j > i) t1.a[j--] += MAXN;
t1.a[i] += MAXN + - t2.a[i];
}
else t1.a[i] -= t2.a[i];
}
t1.len = big;
while(t1.a[t1.len - ] == && t1.len > )
{
t1.len--;
big--;
}
if(flag)t1.a[big - ] = - t1.a[big - ];
return t1;
}
BigNum BigNum::operator * (const BigNum & T) const //重载乘法
{
BigNum ret;
ll i,j,up;
ll temp,temp1;
for(i = ; i < len ; i++)
{
up = ;
for(j = ; j < T.len ; j++)
{
temp = a[i] * T.a[j] + ret.a[i + j] + up;
if(temp > MAXN)
{
temp1 = temp - temp / (MAXN + ) * (MAXN + );
up = temp / (MAXN + );
ret.a[i + j] = temp1;
}
else
{
up = ;
ret.a[i + j] = temp;
}
}
if(up != )
ret.a[i + j] = up;
}
ret.len = i + j;
while(ret.a[ret.len - ] == && ret.len > ) ret.len--;
return ret;
}
BigNum BigNum::operator / (const ll & b) const //重载除法
{
BigNum ret;
ll i,down = ;
for(i = len - ; i >= ; i--)
{
ret.a[i] = (a[i] + down * (MAXN + )) / b;
down = a[i] + down * (MAXN + ) - ret.a[i] * b;
}
ret.len = len;
while(ret.a[ret.len - ] == && ret.len > ) ret.len--;
return ret;
}
ll BigNum::operator % (const ll & b) const //重载取模
{
ll i,d=;
for (i = len-; i>=; i--)
{
d = ((d * (MAXN+))% b + a[i])% b;
}
return d;
}
BigNum BigNum::operator^(const ll & n) const //重载n次方
{
BigNum t,ret();
if(n < )exit(-);
if(n == )return ;
if(n == )return *this;
ll m = n;
while(m > )
{
t = *this;
ll i;
for(i = ; i << <= m; i <<= )
{
t = t * t;
}
m -= i;
ret = ret * t;
if(m == )ret = ret * (*this);
}
return ret;
}
bool BigNum::operator > (const BigNum & T) const //两大整数 大于号重载
{
ll ln;
if(len > T.len) return true;
else if(len == T.len)
{
ln = len - ;
while(a[ln] == T.a[ln] && ln >= ) ln--;
if(ln >= && a[ln] > T.a[ln]) return true;
else return false;
}
else return false;
}
bool BigNum::operator > (const ll & t) const
{
return *this > BigNum(t);
}
bool BigNum::operator < (const BigNum & T) const //两大整数 小于号重载
{
return T > *this;
}
bool BigNum::operator < (const ll & t) const
{
return BigNum(t) > *this;
}
bool BigNum::operator == (const BigNum & T) const //两大整数 等于号重载
{
return !(T > *this) && !(*this > T);
}
bool BigNum::operator == (const ll & t) const
{
return BigNum(t) == *this;
}
void BigNum::print()
{
int i;
cout << a[len - ];
for(i = len - ; i >= ; i--)
{
cout.width(DLEN);
cout.fill('');
cout << a[i];
}
} int main()
{
int n;
cin >> n;
if(n == )puts("");
else if(n == )puts("");
else
{
BigNum a(), b(), c;
for(int i = ; i <= n; i++)
{
c = BigNum(3LL) * b;
c = c - a;
c = c + BigNum(2LL);
a = b;
b = c;
}
cout<<c<<endl;
}
return ;
}

BZOJ 1002 轮状病毒 矩阵树定理的更多相关文章

  1. 【bzoj1002】[FJOI2007]轮状病毒 矩阵树定理+高精度

    题目描述 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道.如下图所示 N轮状病 ...

  2. [bzoj1002]轮状病毒-矩阵树定理

    Brief Description 求外圈有\(n\)个点的, 形态如图所示的无向图的生成树个数. Algorithm Design \[f(n) = (3*f(n-1)-f(n-2)+2)\] Co ...

  3. bzoj 4031: 小Z的房间 矩阵树定理

    bzoj 4031: 小Z的房间 矩阵树定理 题目: 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时 ...

  4. BZOJ 4766: 文艺计算姬 [矩阵树定理 快速乘]

    传送门 题意: 给定一个一边点数为n,另一边点数为m,共有n*m条边的带标号完全二分图$K_{n,m}$ 求生成树个数 1 <= n,m,p <= 10^18 显然不能暴力上矩阵树定理 看 ...

  5. bzoj 4596 [Shoi2016]黑暗前的幻想乡 矩阵树定理+容斥

    4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 559  Solved: 325[Submit][Sta ...

  6. BZOJ 2467: [中山市选2010]生成树(矩阵树定理+取模高斯消元)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2467 题意: 思路:要用矩阵树定理不难,但是这里的话需要取模,所以是需要计算逆元的,但是用辗转相减会 ...

  7. 【BZOJ 4596】 4596: [Shoi2016]黑暗前的幻想乡 (容斥原理+矩阵树定理)

    4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 324  Solved: 187 Description ...

  8. 【BZOJ 1016】 1016: [JSOI2008]最小生成树计数 (DFS|矩阵树定理)

    1016: [JSOI2008]最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树 ...

  9. bzoj 4596: [Shoi2016]黑暗前的幻想乡【容斥原理+矩阵树定理】

    真是简单粗暴 把矩阵树定理的运算当成黑箱好了反正我不会 这样我们就可以在O(n^3)的时间内算出一个无向图的生成树个数了 然后题目要求每个工程队选一条路,这里可以考虑容斥原理:全选的方案数-不选工程队 ...

随机推荐

  1. visual studio清理nuget包缓存

    最近在使用nuget包的时候发现一个问题.昨天我组长明明发了一个新版本的包上去,可在我电脑上死活找不到这个新版本的包.刷新,重启vs,重启电脑,好长时间才出来.今天又碰到这个问题了,在同事电脑上都能搜 ...

  2. MVC中学到的小知识(MVC中的跳转,传参)

    1.mvc中视图中的href="XXX",这个XXX是控制器地址,不是另一个视图.(这里的href语句只能转向控制器,不能直接转向视图),如果要实现转向视图,可以先转到控制器,然后 ...

  3. Cookie写入之path的坑

    问题 我在/page/index/index.html中向浏览器添加了一个useid的cookie(这里没有指定path), 然后试着从/page/demo/demo.html中取值,发现无法取到, ...

  4. 【SSH网上商城项目实战01】整合Struts2、Hibernate4.3和Spring4.2

    转自:https://blog.csdn.net/eson_15/article/details/51277324 今天开始做一个网上商城的项目,首先从搭建环境开始,一步步整合S2SH.这篇博文主要总 ...

  5. Struts2(二)— Result结果配置、Servlet的API的访问、模型驱动、属性驱动

    一.Result结果配置 1.全局和局部结果 ​ 平常我们设置跳转页面,是在action标签里面加上 result标签来控制,这种设置的页面跳转,称之为局部结果页面但是我们有时候在很多个action里 ...

  6. SQL修改表结构

    --(1)向数据库Student表中添加Name字段 use MR_NXT alter table student add Name char(20) --(2)将Student表中Name的字段的数 ...

  7. 多项式乘法,FFT与NTT

    多项式: 多项式?不会 多项式加法: 同类项系数相加: 多项式乘法: A*B=C $A=a_0x^0+a_1x^1+a_2x^2+...+a_ix^i+...+a_{n-1}x^{n-1}$ $B=b ...

  8. Apose.Cell导出的Excel数字格式正确显示

    使用Apose.Cell导出Excel时假如导出的如上图:边框左上角有绿色三角形区域,选中某个区域会出现感叹号询问是否要将文本转换为数字 那么在代码中使用PutValue方法时,后面的bool参数设为 ...

  9. C#-求int数组中连续偶数列的个数

    例如:[3, 3, 2, 2, 2, 4, 3, 5, 4, 6, 3]=>2,2,2,4;4,6 结果为2     [3, 3, 2,3, 2, 2, 4, 3, 5, 4, 6, 3]=&g ...

  10. <Android 应用 之路> MPAndroidChart~ScatterChart

    简介 MPAndroidChart是PhilJay大神给Android开发者带来的福利.MPAndroidChart是一个功能强大并且使用灵活的图表开源库,支持Android和IOS两种,这里我们暂时 ...