生成树的计数(基尔霍夫矩阵):BZOJ 1002 [FJOI2007]轮状病毒

时间:2022-06-14 12:12:06

1002: [FJOI2007]轮状病毒

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 3928  Solved: 2154
[Submit][Status][Discuss]

Description

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

生成树的计数(基尔霍夫矩阵):BZOJ 1002 [FJOI2007]轮状病毒

  N轮状病毒的产生规律是在一个N轮状基中删去若干条边,使得各原子之间有唯一的信息通道,例如共有16个不
同的3轮状病毒,如下图所示

生成树的计数(基尔霍夫矩阵):BZOJ 1002 [FJOI2007]轮状病毒
  现给定n(N<=100),编程计算有多少个不同的n轮状病毒

Input

  第一行有1个正整数n

Output

  计算出的不同的n轮状病毒数输出

Sample Input

3

Sample Output

16
  纯属娱乐~~~
 #ifndef EXTINT_H
#define EXTINT_H #include <cctype>
#include <string>
#include <istream>
#include <ostream>
#include <cassert>
#include <iomanip>
#include <iostream> class ExtInt{
friend ExtInt operator +(const ExtInt &a, const ExtInt &b);
friend ExtInt operator -(const ExtInt &a, const ExtInt &b);
friend ExtInt operator *(const ExtInt &a, const ExtInt &b);
friend ExtInt operator /(const ExtInt &a, const ExtInt &b);
friend ExtInt operator %(const ExtInt &a, const ExtInt &b);
friend bool operator <(const ExtInt &a, const ExtInt &b);
friend bool operator >(const ExtInt &a, const ExtInt &b);
friend bool operator <=(const ExtInt &a, const ExtInt &b);
friend bool operator >=(const ExtInt &a, const ExtInt &b);
friend bool operator ==(const ExtInt &a, const ExtInt &b);
friend bool operator !=(const ExtInt &a, const ExtInt &b);
friend std::istream & operator >>(std::istream &inputStream, ExtInt &data);
friend std::ostream & operator <<(std::ostream &outputStream, const ExtInt &data);
private:
static const int LIMIT = ;
static const int WIDTH = ;
int length;
bool isNegative;
struct DListNode{
int data;
DListNode *forward, *next;
DListNode(int data = ) : data(data), forward(NULL), next(NULL) {}
DListNode & remove();
DListNode & append(DListNode *data);
DListNode & append(const int &data);
DListNode & insert(DListNode *data);
DListNode & insert(const int &data);
}*low, *high;
public:
ExtInt(int data = );
ExtInt(const ExtInt &rhs);
ExtInt(const std::string &rhs);
virtual ~ExtInt(); ExtInt & operator =(const ExtInt &rhs);
ExtInt & operator +=(const ExtInt &rhs);
ExtInt & operator -=(const ExtInt &rhs);
ExtInt & operator *=(const ExtInt &rhs);
ExtInt & operator /=(const ExtInt &rhs);
ExtInt & operator %=(const ExtInt &rhs);
//ExtInt & operator ++();
//ExtInt & operator ++(int);
//ExtInt & operator --();
//ExtInt & operator --(int);
}; #endif ExtInt::DListNode & ExtInt::DListNode::remove() {
DListNode *tmp = this -> forward;
tmp -> forward -> next = this;
this -> forward = tmp -> forward;
delete tmp;
return *this;
}
ExtInt::DListNode & ExtInt::DListNode::append(DListNode *data) {
data -> next = this -> next;
data -> forward = this;
if (this -> next != NULL) {
this -> next -> forward = data;
}
this -> next = data;
return *this;
}
ExtInt::DListNode & ExtInt::DListNode::append(const int &data) {
return append(new DListNode(data));
}
ExtInt::DListNode & ExtInt::DListNode::insert(DListNode *data) {
data -> next = this;
data -> forward = this -> forward;
if (this -> forward != NULL) {
this -> forward -> next = data;
}
this -> forward = data;
return *this;
}
ExtInt::DListNode & ExtInt::DListNode::insert(const int &data) {
return insert(new DListNode(data));
} ExtInt::ExtInt(int data) {
low = new DListNode;
high = new DListNode;
low -> append(high);
length = ;
isNegative = false;
if (data < ) {
isNegative = true;
data = -data;
}
while (data >= ExtInt::LIMIT) {
high -> insert(data % ExtInt::LIMIT);
data /= ExtInt::LIMIT;
length++;
}
if (length == || data > ) {
high -> insert(data);
length++;
}
}
ExtInt::ExtInt(const ExtInt &rhs) {
low = new DListNode;
high = new DListNode;
low -> append(high);
length = ;
isNegative = rhs.isNegative;
for (DListNode *it = rhs.low -> next; it != rhs.high; it = it -> next) {
high -> insert(it -> data);
length++;
}
}
ExtInt::ExtInt(const std::string &rhs) {
low = new DListNode;
high = new DListNode;
low -> append(high);
length = ;
isNegative = false;
if (rhs[] == '-') {
isNegative = true;
}
for (int i = rhs.length() - ; i >= ; i -= WIDTH) {
int value = ;
for (int j = std::max(, i - WIDTH + ); j <= i; j++) {
if (j == && isNegative) continue;
assert(isdigit(rhs[j]));
value = value * + rhs[j] - '';
}
high -> insert(value);
length++;
}
while (length > && high -> forward -> data == ) {
high -> remove();
length--;
}
}
ExtInt & ExtInt::operator =(const ExtInt &rhs) {
if (this == &rhs) return *this;
if (low != NULL || high != NULL) {
this -> ~ExtInt();
}
low = new DListNode;
high = new DListNode;
low -> append(high);
length = ;
isNegative = rhs.isNegative;
for (DListNode *it = rhs.low -> next; it != rhs.high; it = it -> next) {
high -> insert(it -> data);
length++;
}
return *this;
}
ExtInt::~ExtInt() {
for (DListNode *it = low; it != NULL;) {
DListNode *tmp = it -> next;
delete it;
it = tmp;
}
} std::istream & operator >>(std::istream &inputStream, ExtInt &data) {
std::string tmp;
inputStream >> tmp;
data = ExtInt(tmp);
return inputStream;
}
std::ostream & operator <<(std::ostream &outputStream, const ExtInt &data) {
if (data.isNegative) {
outputStream << "-";
}
ExtInt::DListNode *it = data.high -> forward;
outputStream << it -> data;
for (it = it -> forward; it != data.low; it = it -> forward) {
outputStream << std::setfill('') << std::setw(ExtInt::WIDTH) << it -> data;
}
return outputStream;
} bool operator <(const ExtInt &a, const ExtInt &b) {
if (a.isNegative && !b.isNegative) return true;
if (!a.isNegative && b.isNegative) return false;
bool flag = false;
if (a.isNegative && b.isNegative) flag = true;
if (a.length < b.length) return flag ^ true;
if (a.length > b.length) return flag ^ false;
ExtInt::DListNode *itA = a.high, *itB = b.high;
for (; itA != a.low && itB != b.low; itA = itA -> forward, itB = itB -> forward) {
if (itA -> data < itB -> data) return flag ^ true;
if (itA -> data > itB -> data) return flag ^ false;
}
return false;
}
bool operator >(const ExtInt &a, const ExtInt &b) {
if (a.isNegative && !b.isNegative) return false;
if (!a.isNegative && b.isNegative) return true;
bool flag = false;
if (a.isNegative && b.isNegative) flag = true;
if (a.length < b.length) return flag ^ false;
if (a.length > b.length) return flag ^ true;
ExtInt::DListNode *itA = a.high, *itB = b.high;
for (; itA != a.low && itB != b.low; itA = itA -> forward, itB = itB -> forward) {
if (itA -> data < itB -> data) return flag ^ false;
if (itA -> data > itB -> data) return flag ^ true;
}
return false;
}
bool operator >=(const ExtInt &a, const ExtInt &b) {
return !(a < b);
}
bool operator <=(const ExtInt &a, const ExtInt &b) {
return !(a > b);
}
bool operator ==(const ExtInt &a, const ExtInt &b) {
if (a.isNegative != b.isNegative) return false;
if (a.length != b.length) return false;
ExtInt::DListNode *itA = a.low, *itB = b.low;
for (; itA != a.high && itB != b.high; itA = itA -> next, itB = itB -> next) {
if (itA -> data != itB -> data) return false;
}
return true;
}
bool operator !=(const ExtInt &a, const ExtInt &b) {
return !(a == b);
} ExtInt operator +(const ExtInt &a, const ExtInt &b) {
if (b.isNegative) {
ExtInt tmp = b;
tmp.isNegative = false;
return a - tmp;
}
if (a.isNegative) {
ExtInt tmp = a;
tmp.isNegative = false;
return b - tmp;
}
ExtInt ret = a;
ExtInt::DListNode *itA = ret.low -> next, *itB = b.low -> next;
for (; itB != b.high; itA = itA -> next, itB = itB -> next) {
if (itA == ret.high) {
itA -> insert();
ret.length++;
itA = itA -> forward;
}
itA -> data += itB -> data;
if (itA -> data >= ExtInt::LIMIT) {
if (itA -> next == ret.high) {
itA -> append();
ret.length++;
}
itA -> next -> data += itA -> data / ExtInt::LIMIT;
itA -> data %= ExtInt::LIMIT;
}
}
return ret;
}
ExtInt operator -(const ExtInt &a, const ExtInt &b) {
if (b.isNegative) {
ExtInt tmp = b;
tmp.isNegative = false;
return a + tmp;
}
if (a.isNegative) {
ExtInt tmp = a;
tmp.isNegative = false;
tmp = tmp + b;
tmp.isNegative = true;
return tmp;
}
if (a < b) {
ExtInt tmp = b - a;
tmp.isNegative = true;
return tmp;
}
ExtInt ret = a;
ExtInt::DListNode *itA = ret.low -> next, *itB = b.low -> next;
for (; itA != ret.high && itB != b.high; itA = itA -> next, itB = itB -> next) {
itA -> data -= itB -> data;
if (itA -> data < ) {
itA -> data += ExtInt::LIMIT;
itA -> next -> data--;
}
}
for (; itA != ret.high; itA = itA -> next) {
if (itA -> data < ) {
itA -> data += ExtInt::LIMIT;
itA -> next -> data--;
}
}
while (ret.length > && ret.high -> forward -> data == ) {
ret.high -> remove();
ret.length--;
}
return ret;
}
ExtInt operator *(const ExtInt &a, const ExtInt &b) {
if (a == ExtInt() || b == ExtInt()) return ExtInt();
ExtInt ret, tmp;
ExtInt::DListNode *itB = b.low -> next;
for (int value = ; itB != b.high; itB = itB -> next, value++) {
if (itB -> data == ) {
continue;
}
tmp = a;
ExtInt::DListNode *itA = tmp.low -> next;
for (long long r = ; itA != tmp.high; itA = itA -> next) {
long long now = 1ll * itA -> data * itB -> data + r;
itA -> data = now % ExtInt::LIMIT;
r = ;
if (now >= ExtInt::LIMIT) {
if (itA -> next == tmp.high) {
itA -> append();
tmp.length++;
}
r = now / ExtInt::LIMIT;
}
}
for (int i = ; i <= value; i++) {
tmp.low -> append();
tmp.length++;
}
//std::cerr << ret << std::endl;
//std::cerr << tmp << std::endl;
//std::cerr << tmp.length << std::endl;
ret = ret + tmp;
}
ret.isNegative = a.isNegative ^ b.isNegative;
return ret;
}
ExtInt operator /(const ExtInt &a, const ExtInt &b) {
assert(b != ExtInt());
if (a == ExtInt()) return ExtInt();
ExtInt ret, tmp, div = b;
ret.high -> remove();
ret.length = ;
tmp.high -> remove();
tmp.length = ;
div.isNegative = false;
ExtInt::DListNode *itA = a.high -> forward;
for (; itA != a.low; itA = itA -> forward) {
tmp.low -> append(itA -> data);
tmp.length++;
if (tmp >= div) {
int left = , right = ExtInt::LIMIT - ;
while (left < right) {
int middle = (left + right >> ) + ;
if (tmp >= div * middle) {
left = middle;
} else {
right = middle - ;
}
}
//std::cerr << tmp << " " << div * left << std::endl;
ret.low -> append(left);
ret.length++;
tmp = tmp - div * left;
} else {
ret.low -> append();
ret.length++;
}
if (tmp == ExtInt()) {
tmp.high -> remove();
tmp.length = ;
}
}
while (ret.length > && ret.high -> forward -> data == ) {
ret.high -> remove();
ret.length--;
}
ret.isNegative = a.isNegative ^ b.isNegative;
if (ret.isNegative && tmp.low -> next != tmp.high) {
ret = ret - ;
}
return ret;
}
ExtInt operator %(const ExtInt &a, const ExtInt &b) {
return a - a / b * b;
} ExtInt & ExtInt::operator +=(const ExtInt &rhs) {
*this = *this + rhs;
return *this;
}
ExtInt & ExtInt::operator -=(const ExtInt &rhs) {
*this = *this - rhs;
return *this;
}
ExtInt & ExtInt::operator *=(const ExtInt &rhs) {
*this = *this * rhs;
return *this;
}
ExtInt & ExtInt::operator /=(const ExtInt &rhs) {
*this = *this / rhs;
return *this;
}
ExtInt & ExtInt::operator %=(const ExtInt &rhs) {
*this = *this % rhs;
return *this;
}
#include <iostream>
#include <cstdio>
using namespace std;
int n;
const int maxn=;
ExtInt C[maxn][maxn];
void abs(ExtInt &x){
if(x<)x=x*(-);
}
void Solve(){
for(int i=;i<n;i++){
for(int j=i+;j<n;j++)
while(C[j][i]!=){
ExtInt r=C[i][i]/C[j][i];
for(int k=i;k<n;k++)
C[i][k]-=C[j][k]*r;
swap(C[i],C[j]);
}
}
ExtInt ans=;
for(int i=;i<n;i++)
ans*=C[i][i];
abs(ans);
cout<<ans<<endl;
return;
}
int main(){
scanf("%d",&n);n++;
if(n!=)
for(int i=;i<n;i++){
C[i][i%(n-)+]-=;
C[i%(n-)+][i]-=;C[i][i]+=;
C[i%(n-)+][i%(n-)+]+=;
}
for(int i=;i<n;i++){
C[i][n]=-;
C[n][i]=-;
C[i][i]+=;
C[n][n]+=;
}
Solve();
return ;
}

生成树的计数(基尔霍夫矩阵):BZOJ 1002 [FJOI2007]轮状病毒的更多相关文章

  1. 生成树的计数&lpar;基尔霍夫矩阵&rpar;:UVAoj 10766 Organising the Organisation SPOJ HIGH - Highways

    HIGH - Highways   In some countries building highways takes a lot of time... Maybe that's because th ...

  2. 无向图生成树计数 基尔霍夫矩阵 SPOJ Highways

    基尔霍夫矩阵 https://blog.csdn.net/w4149/article/details/77387045 https://blog.csdn.net/qq_29963431/articl ...

  3. BZOJ 4031 HEOI2015 小Z的房间 基尔霍夫矩阵&plus;行列式&plus;高斯消元 (附带行列式小结)

    原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4031 Description 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可 ...

  4. BZOJ 1002&colon; &lbrack;FJOI2007&rsqb;轮状病毒【生成树的计数与基尔霍夫矩阵简单讲解&plus;高精度】

    1002: [FJOI2007]轮状病毒 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 5577  Solved: 3031[Submit][Statu ...

  5. 疯子的算法总结&lpar;九&rpar; 图论中的矩阵应用 Part 2 矩阵树 基尔霍夫矩阵定理 生成树计数 Matrix-Tree

    定理: 1.设G为无向图,设矩阵D为图G的度矩阵,设C为图G的邻接矩阵. 2.对于矩阵D,D[i][j]当 i!=j 时,是一条边,对于一条边而言无度可言为0,当i==j时表示一点,代表点i的度. 即 ...

  6. 【BZOJ】1002:轮状病毒(基尔霍夫矩阵【附公式推导】或打表)

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

  7. bzoj 1002 &lbrack;FJOI2007&rsqb;轮状病毒 高精度&amp&semi;&amp&semi;找规律&amp&semi;&amp&semi;基尔霍夫矩阵

    1002: [FJOI2007]轮状病毒 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2234  Solved: 1227[Submit][Statu ...

  8. bzoj 1002 找规律(基尔霍夫矩阵)

    网上说的是什么基尔霍夫矩阵,没学过这个,打个表找下规律,发现 w[i]=3*w[i-1]-w[i-2]+2; 然后写个高精直接递推就行了 //By BLADEVIL var n :longint; a ...

  9. bzoj1002 轮状病毒 暴力打标找规律&sol;基尔霍夫矩阵&plus;高斯消元

    基本思路: 1.先观察规律,写写画画未果 2.写程序暴力打表找规律,找出规律 1-15的答案:1    5    16    45    121 320 841     2205   5776 151 ...

随机推荐

  1. iOS 开发 常用的正则验证表达式:电话 、邮箱等等

    #pragma mark - 验证手机号 +(BOOL)checkForMobilePhoneNo:(NSString *)mobilePhone{ NSString *regEx = @" ...

  2. BZOJ-1067 降雨量 线段树&plus;分类讨论

    这道B题,刚的不行,各种碎点及其容易忽略,受不鸟了直接 1067: [SCOI2007]降雨量 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 2859 ...

  3. pager分页框架体会

    <pg:pager> 元素的属性中: maxPageItems说的是每页偏移量是多少,这个并不是说每一页显示多少,而是第二页比第一页来说,在第一页的尾部增加多少,第一页又被覆盖多少,是决定 ...

  4. LaTeX入门教程

    LaTeX(LATEX,音译"拉泰赫")是一种基于ΤΕΧ的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在20世纪80年代初期开发,利用这种格式,即使使用 ...

  5. SQLServer 发布订阅(Replication)造成的Memroy压力(cmemthread等待)

    深入了解下发布订阅:     数据复制:允许一个数据源向一个或多个目标数据库分发数据,只需要OLE DB 访问接口即可访问: 整个复制框架包含:复制组件,复制代理,复制类型: 复制组件: 发布服务器: ...

  6. 01&lowbar;Linux安装

    一.VMware创建一个虚拟机 下一步   .下一步  .下一步 ..前方高能 二.安装CentOS 6.7 next  ->  选择 中文简体  -> 美式键盘,直接下一步  ,一直下一 ...

  7. ElasticSearch、Logstash、Kibana 搭建高效率日志管理系统

    ELK (ElasticSearch.LogStash以及Kibana)三者组合是一个非常强大的工具,这里我们来实现监控日志文件并且收到日志到ElasticSearch搜索引擎,利用Kibana可视化 ...

  8. mui 记录

    1.轮播添加无限循环 需要在 .mui-slider-group节点上增加.mui-slider-loop类 2.web移动端侧滑与滑动同时存在 参考https://segmentfault.com/ ...

  9. 浅谈Kotlin(一):简介及Android Studio中配置

    浅谈Kotlin(一):简介及Android Studio中配置 浅谈Kotlin(二):基本类型.基本语法.代码风格 浅谈Kotlin(三):类 浅谈Kotlin(四):控制流 前言: 今日新闻:谷 ...

  10. 安卓AlertDialog 的使用

    引入空间 import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; fin ...