1002: [FJOI2007]轮状病毒

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 6917  Solved: 3777
[Submit][Status][Discuss]

Description

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

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

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

Input

  第一行有1个正整数n

Output

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

Sample Input

3

Sample Output

16

HINT

Source


题解:

        一道及其艰辛的推导题;(感觉bzoj的前两个题对新人不太友好啊)

        当然可以用基尔霍夫矩阵;

        打表可得$g_i = 3g_{i-1} - g_{i-2} + 2$;再用一个高精度就好了   

 #include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cmath>
#include<vector>
#include<stack>
#include<map>
#define Run(i,l,r) for(int i=l;i<=r;i++)
#define Don(i,l,r) for(int i=l;i>=r;i--)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int N=,base = 1e4;
int n;
struct Bign{
int c[N],len;
Bign(){memset(c,,sizeof(c));len=;}
void zero(){while(len&&!c[len])len--;}
void print(){
zero();
printf("%d",c[len]);
Don(i,len-,)printf("%04d",c[i]);
puts("");
}
Bign operator -(const Bign&A){
Bign ret;
ret.len = len;
for(int i=;i<=len;i++){
ret.c[i] += c[i] - A.c[i];
if(ret.c[i]<){
ret.c[i] += base;
ret.c[i + ] --;
}
}
ret.zero();
return ret;
}
Bign operator +(const int&A){
Bign ret;
ret = *this;
ret.len = len + ;
ret.c[] += A;
for(int i=;i<=len;i++){
if(ret.c[i]>=base){
ret.c[i] -= base;
ret.c[i+] ++;
}
}
ret.zero();
return ret;
}
Bign operator *(const int&A){
Bign ret;
ret.len = len + ;
for(int i=;i<=len;i++){
ret.c[i] = c[i] * A;
}
for(int i=;i<=len;i++){
if(ret.c[i]>=base){
ret.c[i+]+=ret.c[i]/base;
ret.c[i] %= base;
}
}
ret.zero();
return ret;
}
}f[N];
int main(){
freopen("bzoj1002.in","r",stdin);
freopen("bzoj1002.out","w",stdout);
scanf("%d",&n);
f[].len = ;
f[].c[] = ;
f[].len = ;
f[].c[] = ;
//f[1].print();
//f[2].print();
for(int i=;i<=n;i++){
f[i] = f[i-]* - f[i-] + ;
// f[i].print();
}
f[n].print();
return ;
}//by tkys_Austin;

      可以用递推证明:
①先不考虑中间的点,最后再将中间的点和外面的点连起来,假设某种方案将外面的环分成了i条链,
每条的点数为si,每个链都可以任选一个点连上中间的点,这种方案的贡献就为$\prod_i si$,

设长度为i的链分成若干链的$\sum \prod_i si$为$f_i$,轮状病毒的总方案的为$g_i$

$g_n$的转移枚举第一个点所在的链的长度s1,此时1的位置一共有s1种可能,再乘上剩下的长度为n-s1的链的方案数$f_{n-s1}$;

$f_n$的转移枚举最后一段链的长度,用最后一段链的长度乘剩下的$f_j$

$$\left\{\begin{array}{c}f_0 = 1\\f_i = \sum_{j=0}^{i} (j-i)f_j\end{array}\right.$$ 

$$\left \{ \begin{array}{c} g_0 = 1\\g_i = \sum_{j=0}^{i} (j-i)^2 {f_j} \end{array}\right.$$

我们先证明:$f_{i-1} + f_{i+1} = 3f_{i}$

$$f_{i-1} + f_{i+1}\\= \sum_{j=0}^{i-1}(i-1-j)f_{j} + \sum_{j=0}^{i+1}(i+1-j)f_{j} \\= \sum_{j=0}^{i-1}2(i-j)f_{j} + f_i \\= 2 \sum_{j=0}^{i}(i-j)f_{j} + f_i \\= 2 f_i + f_i \\= 3 f_i $$

再对g同样操作:     

$$g_{i-1} + g_{i+1} \\
= \sum_{j=0}^{i+1}(i+1-j)^2 f_j + \sum_{j=0}^{i-1}(i-1-j)^2 f_j \\
= \sum_{j=0}^{i-1}((i+1-j)^2 + (i-1-j)^2) f_j + f_i \\
= \sum_{j=0}^{i-1}2((i-j)^2 + 1)f_j + f_i \\
= 2 \sum_{j=0}^{i}(i-j)^2 f_j + 2 \sum_{j=0}^{i-1}f_j + f_i \\
= 2 g_i + 2 + 2 \sum_{j=1}^{i-1}f_j + fi \\
$$

尝试把右边那坨化成理想的目标$g_i$:

$$2\sum_{j=1}^{i-1}f_{j} + f_{i} \\
= 2\sum_{j=1}^{i-1}\sum_{k=0}^{j}(j-k)f_{k} + f_{i} $$
改变一下求和顺序 \\
$$= 2\sum_{k=0}^{i-1}f_{k} \sum_{j>k}^{i-1}(j-k) + f_{i} $$
不知道我下标写对没有。。。后面的1直接求 \\

$$= 2\sum_{k=0}^{i-1}f_{k} \frac{(i-1-k)(i-k)}{2} + f_{i} $$

看到分子出现2,感觉有希望QAQ,约掉

$$  =  \sum_{k=0}^{i-1}f_{k} (i-1-k)(i-k) + f_{i} $$ $$  = \sum_{k=0}^{i-1}(i-k)^2 f_{k} - \sum_{k=0}^{i-1}(i-k)f_{k} + f_{i} $$ $$  = \sum_{j=0}^i    (i-j)^{2}   f_j   -   \sum_{j=0}^i   (i-j)   f_j   +   f_i$$ $$  = g_{i} - f_{i} + f_{i} \\= g_{i}   $$

带回去就是原来的式子了。。。。。。。。。

(mathjax好难用。。。。。)

BZOJ1002【FJOI2007】轮状病毒的更多相关文章

  1. BZOJ1002 FJOI2007 轮状病毒 【基尔霍夫矩阵+高精度】

    BZOJ1002 FJOI2007 轮状病毒 Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2个原 ...

  2. [bzoj1002][FJOI2007]轮状病毒_递推_高精度

    轮状病毒 bzoj-1002 FJOI-2007 Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2 ...

  3. bzoj1002: [FJOI2007]轮状病毒(基尔霍夫矩阵)

    1002: [FJOI2007]轮状病毒 题目:传送门 题解: 决定开始板刷的第一题... 看到这题的时候想:这不就是求有多少种最小生成树的方式吗? 不会啊!!!%题解... 什么鬼?基尔霍夫矩阵?? ...

  4. BZOJ1002[FJOI2007]轮状病毒

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

  5. [bzoj1002][FJOI2007 轮状病毒] (生成树计数+递推+高精度)

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

  6. [BZOJ1002] [FJOI2007] 轮状病毒 (数学)

    Description 给定n(N<=100),编程计算有多少个不同的n轮状病毒. Input 第一行有1个正整数n. Output 将编程计算出的不同的n轮状病毒数输出 Sample Inpu ...

  7. [luogu2144][bzoj1002][FJOI2007]轮状病毒【高精度+斐波那契数列+基尔霍夫矩阵】

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

  8. bzoj1002: [FJOI2007]轮状病毒 生成树计数

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

  9. BZOJ1002:[FJOI2007]轮状病毒(找规律,递推)

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

  10. [bzoj1002] [FJOI2007]轮状病毒轮状病毒(基尔霍夫矩阵)

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

随机推荐

  1. 视觉SLAM中的深度估计问题

    一.研究背景 视觉SLAM需要获取世界坐标系中点的深度. 世界坐标系到像素坐标系的转换为(深度即Z): 深度的获取一共分两种方式: a)主动式 RGB-D相机按照原理又分为结构光测距.ToF相机 To ...

  2. TensorFlow深度学习实战---MNIST数字识别问题

    1.滑动平均模型: 用途:用于控制变量的更新幅度,使得模型在训练初期参数更新较快,在接近最优值处参数更新较慢,幅度较小 方式:主要通过不断更新衰减率来控制变量的更新幅度. 衰减率计算公式 : deca ...

  3. Spring学习(3):Spring概述(转载)

    1. Spring是什么? Spring是一个开源的轻量级Java SE(Java 标准版本)/Java EE(Java 企业版本)开发应用框架,其目的是用于简化企业级应用程序开发. 在面向对象思想中 ...

  4. 基于C#的机器学习--颜色混合-自组织映射和弹性神经网络

    自组织映射和弹性神经网络 自组织映射(SOM),或者你们可能听说过的Kohonen映射,是自组织神经网络的基本类型之一.自组织的能力提供了对以前不可见的输入数据的适应性.它被理论化为最自然的学习方式之 ...

  5. 实现属于自己的TensorFlow(二) - 梯度计算与反向传播

    前言 上一篇中介绍了计算图以及前向传播的实现,本文中将主要介绍对于模型优化非常重要的反向传播算法以及反向传播算法中梯度计算的实现.因为在计算梯度的时候需要涉及到矩阵梯度的计算,本文针对几种常用操作的梯 ...

  6. python中Requests模块中https请求在设置为忽略有效性验证,屏蔽告警信息的方式

    增加下面的就ok了from requests.packages.urllib3.exceptions import InsecureRequestWarningrequests.packages.ur ...

  7. 总结在Visual Studio Code运行node.js项目遇到的问题

    一.cannot find module “lodash” 项目运行时出现以下错误: Error: Cannot find module 'lodash' at Function.Module._re ...

  8. python __call__ 函数

    __call__ Python中有一个有趣的语法,只要定义类型的时候,实现__call__函数,这个类型就成为可调用的. 换句话说,我们可以把这个类型的对象当作函数来使用,相当于 重载了括号运算符. ...

  9. EXT4+Struts2 JSON的问题

    ERROR : Class org.apache.struts2.json.JSONWriter can not access a member of class org.springframewor ...

  10. mysql---增删用户

    Mysql创建.删除用户 MySql中添加用户,新建数据库,用户授权,删除用户,修改密码(注意每行后边都跟个  ;  表示一个命令语句结束): 1.新建用户 登录MYSQL: @>mysql - ...