BZOJ 1002 轮状病毒 矩阵树定理
题目链接:
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 轮状病毒 矩阵树定理的更多相关文章
- 【bzoj1002】[FJOI2007]轮状病毒 矩阵树定理+高精度
题目描述 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道.如下图所示 N轮状病 ...
- [bzoj1002]轮状病毒-矩阵树定理
Brief Description 求外圈有\(n\)个点的, 形态如图所示的无向图的生成树个数. Algorithm Design \[f(n) = (3*f(n-1)-f(n-2)+2)\] Co ...
- bzoj 4031: 小Z的房间 矩阵树定理
bzoj 4031: 小Z的房间 矩阵树定理 题目: 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时 ...
- BZOJ 4766: 文艺计算姬 [矩阵树定理 快速乘]
传送门 题意: 给定一个一边点数为n,另一边点数为m,共有n*m条边的带标号完全二分图$K_{n,m}$ 求生成树个数 1 <= n,m,p <= 10^18 显然不能暴力上矩阵树定理 看 ...
- bzoj 4596 [Shoi2016]黑暗前的幻想乡 矩阵树定理+容斥
4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 559 Solved: 325[Submit][Sta ...
- BZOJ 2467: [中山市选2010]生成树(矩阵树定理+取模高斯消元)
http://www.lydsy.com/JudgeOnline/problem.php?id=2467 题意: 思路:要用矩阵树定理不难,但是这里的话需要取模,所以是需要计算逆元的,但是用辗转相减会 ...
- 【BZOJ 4596】 4596: [Shoi2016]黑暗前的幻想乡 (容斥原理+矩阵树定理)
4596: [Shoi2016]黑暗前的幻想乡 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 324 Solved: 187 Description ...
- 【BZOJ 1016】 1016: [JSOI2008]最小生成树计数 (DFS|矩阵树定理)
1016: [JSOI2008]最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树 ...
- bzoj 4596: [Shoi2016]黑暗前的幻想乡【容斥原理+矩阵树定理】
真是简单粗暴 把矩阵树定理的运算当成黑箱好了反正我不会 这样我们就可以在O(n^3)的时间内算出一个无向图的生成树个数了 然后题目要求每个工程队选一条路,这里可以考虑容斥原理:全选的方案数-不选工程队 ...
随机推荐
- java并发编程(4)性能与可伸缩性
性能与可伸缩性 一.Amdahl定律 1.问题和资源的关系 在某些问题中,资源越多解决速度越快:而有些问题则相反: 注意:每个程序中必然有串行的部分,而合理的分析出串行和并行的部分对程序的影响极大:串 ...
- Web前端学习资料
http://www.imooc.com/course/list?c=html http://www.w3cplus.com/ http://www.w3cfuns.com/ http://www.w ...
- HTML基础-常用标签及图片
标记/标签{元素} 双标签: <标签>内容</标签> <html></html> 网页 页面的根元素 <head></head& ...
- Spring与SpringMVC的关系
在此鉴于你已经了解过Spring的相关知识,简单描述一下Spring与Spring的关系 在框架的使用中,Spring类似于一个具有多种特性,也可以说是多种功能模块的应用平台,(特性就比如IoC,AO ...
- 一:Bootstrap-css样式
页面大块布局: div.container 栅格系统: 一行分成 12 列 div.row div.col-md-12 div.col-xs-12 <div class="row&qu ...
- SSM maven框架下载简易版
1.前台一个a标签,写个地址就行了 例如 <a href="${pageContext.request.contextPath}/fileDownLoad">前去下载& ...
- linux ssh免密登陆
大致流程: 两台linux系统A B 如果A要登陆到B 1.生成A的密钥对 2.将A的公钥拷贝到B的authorized_keys中即可 可以使用命令:ssh-copy-id -i ~/.ssh/id ...
- Mac PHPStorm快捷键总结
全局搜索(command + shift + F) 显示类中的方法 (command + 7) 函数追踪 (command +鼠标点击) 单行注释/取消(command + /) 输入行号跳到某一行( ...
- Struts 类型转换之局部和全局配置
我们碰到过很多情况,就是时间日期常常会出现错误,这是我们最头疼的事,在struts2中有一些内置转换器,也有一些需要我们自己配置. 我们为什么需要类型转换呢? 在基于HTTP协议的Web应用中 客户端 ...
- Conda常用命令整理
主要参考Anaconda官方指南Using Conda:https://conda.io/docs/using/index.html 环境:Win10 64bit with conda 4.3.14 ...