题目链接:

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. 使用 Angular 和 RxJS 实现的无限滚动加载

    无限滚动加载应该是怎样的? 无限滚动加载列表在用户将页面滚动到指定位置后会异步加载数据.这是避免寻主动加载(每次都需要用户去点击)的好方法,而且它能真正保持应用的性能.同时它还是降低带宽和增强用户体验 ...

  2. Jquery 搜索框自动提示

    为文本框增加自动提示下拉功能,比如输入 1,则从后台数据库查询出包含1 的字段,在文本框增加下拉列表供用户选择 ajax 返回数据为搜索查询字段的json集合 <script src=" ...

  3. 关于vue.js父子组件数据传递

    vue.js中使用props down,events up的原则进行父子组件间的通信,先来记录下props down,看个例子: <div id="app2"> < ...

  4. css 样式加载次序

    一般而言,所有的样式会根据下面的规则层叠于一个新的虚拟样式表中,其中数字 4 拥有最高的优先权(本人理解为:先加载1的样式,然后用2的样式覆盖1中的样式,3.4同理) 浏览器缺省设置(浏览器默认的样式 ...

  5. PoPo数据可视化周刊第2期

    羡辙在bilibili开课啦 就在这个月,不知道是不是受了 @Jannchie见齐 的影响,羡辙竟然在bilibili开授Echarts课程,目前已开课两节. [滚城一团]的 ECharts 训练营 ...

  6. Bzoj3597: [Scoi2014]方伯伯运椰子

    题面 传送门 Sol 消圈定理:如果一个费用流网络的残量网络有负环,那么这个费用流不优 于是这个题就可以建出残量网络,然后分数规划跑负环了 # include <bits/stdc++.h> ...

  7. JavaScript的进阶之路(四)理解对象1

    对象是JavaScript的基本数据类型.简单的名值对组成了对象,BUT:还可以从一个被称为原型的对象继承属性,对象的方法通常就是继承的属性. 对象最常见的用法有:创建.设置.查找.删除.检测.枚举它 ...

  8. 初级篇html。

    什么是html?  超文本标记语言,标准通用标记语言下的一个应用. “超文本”就是指页面内可以包含图片.链接,甚至音乐.程序等非文字元素. 超文本标记语言的结构包括“头”部分(英语:Head).和“主 ...

  9. jQuery 滚动条滚动

    1.将div的滚动条滚动到最底端 <div class="container"></div> var $container=$(".contain ...

  10. MongoDB 排序文档

    sort() 方法 要在 MongoDB 中的文档进行排序,需要使用sort()方法. sort() 方法接受一个文档,其中包含的字段列表连同他们的排序顺序. 要指定排序顺序1和-1. 1用于升序排列 ...