什么都不说先甩题目

Description

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

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

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

 

Input

  第一行有1个正整数n

Output

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

Sample Input

3

Sample Output

16

  这道题其实思路应该是生成树计数问题,但是很明显的,本题给出的数据范围对于一般使用的Matrix-Tree定理(Kirchhoff矩阵-树定理)来说数据范围有点大,所以在这里Matrix-Tree只作为暴力算法,正解得出的方法是用奇怪的递推式。

  首先来讲讲Matrix-tree,具体方法是这样:

  一,首先得出一个点的度的矩阵A,定义为:对于当前矩阵A[i][j]来说,只有在当前i=j的情况下,A[i][j]为第i个点的度数,其他点为0;

  二,得出一个关于边的矩阵B,定义为:对于当前的矩阵B[i][j]来说,当i与j相连的情况下,B[i][j]为1,其他点为0;

  最后得出一个最终矩阵C,对于C的定义为:C[i][j]=A[i][j] - B[i][j];

  我们在最后的计算前要对矩阵C做一件玄学的事情:以一个对角线数字作为关键点,消掉该关键带点所在横行于纵行所有点(包括自己),把剩下的点再拼成矩阵C(事关玄学);

  接下来就很简单了,把新矩阵C当做一组线性方程,然后用高斯消元对C来求解(只需要把由对角线切开的任意一个数字三角上的数全消为0即可),然后把对角线上的数字全部相乘,得出解;

  贴出以这种方法写的n<20的暴力

  1. #include<stdio.h>
  2. double mp[][];
  3. int n;
  4. int main()
  5. {
  6. scanf("%d",&n);
  7. if(n==){printf("");return ;}//来组特判
  8. if(n==){printf("");return ;}
  9. mp[][]=,mp[][n]=-,mp[][]=-,mp[n][n]=,mp[n][]=-,mp[n][n-]=-;
  10. for(int i=;i<n;i++)mp[i][i-]=mp[i][i+]=-,mp[i][i]=;//以下是建立矩阵的过程
  11. for(int i=;i<=n;++i)//对于这道题,把中间的点看做要消掉的点,建矩阵方法因人而异
  12. {
  13. for(int j=;j<i;++j)
  14. {
  15. double shit=(-mp[i][j])/mp[j][j];
  16. for(int k=j;k<=n;++k)
  17. mp[i][k]+=mp[j][k]*shit;
  18. }
  19. }
  20. double ans=;
  21. for(int i=;i<=n;i++)
  22. ans*=mp[i][i];
  23. printf("%d",(int)(ans+0.5));//四舍五入
  24. return ;
  25. }

Matrix-tree

  但是这样并不能A,所以我们要想一种更优的解,

  根据对打表数据的判断,可以得出g[i]=3*g[i-1]-g[i-2]+2的神奇结论;

  这个公式好像要依靠对于数论的理解来分析(对于新加入的点对于全图的关系),得出递推式。

  贴出正解代码

  1. #include<stdio.h>
  2. struct shit{
  3. int a[],len;
  4. }g[];
  5. int n;
  6. shit c(shit x,int y)
  7. {
  8. for(int i=;i<=x.len;i++)x.a[i]*=y;
  9. for(int i=;i<=x.len;i++)
  10. {
  11. x.a[i+]+=x.a[i]/;
  12. x.a[i]%=;
  13. }
  14. if(x.a[x.len+])x.len++;
  15. return x;
  16. }
  17. shit j(shit x,shit y)
  18. {
  19. x.a[]+=;
  20. int s=x.len;
  21. shit z;
  22. for(int i=;i<=x.len;i++)
  23. {
  24. if(x.a[i]<y.a[i])x.a[i+]--,x.a[i]+=;
  25. x.a[i]=x.a[i]-y.a[i];
  26. }
  27. while(x.a[x.len]==)x.len--;
  28. return x;
  29. }
  30. int main()
  31. {
  32. scanf("%d",&n);
  33. g[].a[]=,g[].len=;
  34. g[].a[]=,g[].len=;
  35. for(int i=;i<=n;++i)
  36. g[i]=j(c(g[i-],),g[i-]);
  37. for(int i=g[n].len;i>=;i--)printf("%d",g[n].a[i]);
  38. return ;
  39.  
  40. }

另外还有一种思路提供参考

【规律】这里是1--15的打表情况:1 5 16 45 121 320 841 2205 5776 15125 39601 103680 271441 710645 1860496。很快先发现一个规律:第1、3、5、7位是平方数,2、4、6、8位除以5后也是平方数。

    然后再整理:1*1 5*1*1 4*4 5*3*3 11*11 5*8*8 29*29 5*21*21 76*76 5*55*55 199*199 5*144*144 521*521。看着奇数位1,3,8,21,55。。。。。。灵光一现:这不是斐波那契的一半吗:1,2,3,5,8,13,21,24,55.。。。。。另外一个也能表示成类似的相加的数列:

奇数位:1 3 4 7 11 18 29 76

偶数位:1 2 3 5 8 13 21 34 55

主要结论来自于:http://blog.csdn.net/jiangshibiao/article/details/22645557

然后贴出以这种方式A的神犇的代码

  1. #include<cstdio>
  2. #include<cstring>
  3. using namespace std;
  4. const int size=; //这里的位数卡着n=100的情况,为了加速。
  5. struct arr{int num,p[size];}a,b,c;
  6. int i,n,j;
  7. arr add(arr a,arr b)
  8. {
  9. arr c;memset(c.p,,sizeof(c.p));
  10. c.num=a.num>b.num?a.num:b.num;
  11. for (int i=;i<=c.num;i++)
  12. c.p[i]=a.p[i]+b.p[i];
  13. for (int i=;i<=c.num;i++)
  14. c.p[i+]+=c.p[i]/,c.p[i]%=;
  15. if (c.p[c.num+]) c.num++;
  16. return c;
  17. }
  18. arr chen(arr a,arr b)
  19. {
  20. arr c;memset(c.p,,sizeof(c.p));
  21. for (int i=;i<=a.num;i++)
  22. for (int j=;j<=b.num;j++)
  23. c.p[i+j-]+=a.p[i]*b.p[j];
  24. c.num=a.num+b.num-;
  25. for (int i=;i<=c.num;i++)
  26. c.p[i+]+=c.p[i]/,c.p[i]%=;
  27. while (c.p[c.num+])
  28. {
  29. c.num++;c.p[c.num+]+=c.p[c.num]/;c.p[c.num]%=;
  30. }
  31. return c;
  32. }
  33. int main()
  34. {
  35. scanf("%d",&n);
  36. switch (n)
  37. {
  38. case :{printf("");return ;}
  39. case :{printf("");return ;}
  40. case :{printf("");return ;}
  41. }
  42. if (n%==)
  43. {
  44. a.p[]=;b.p[]=;a.num=;b.num=;
  45. for (i=;i<=n;i++)
  46. {
  47. c=add(a,b);
  48. a.num=b.num;for (j=;j<=a.num;j++) a.p[j]=b.p[j];
  49. b.num=c.num;for (j=;j<=b.num;j++) b.p[j]=c.p[j];
  50. }
  51. c=chen(c,c);
  52. memset(a.p,,sizeof(a.p));a.p[]=;a.num=;c=chen(c,a);
  53. for (i=c.num;i>;i--)
  54. printf("%d",c.p[i]);
  55. }
  56. else
  57. {
  58. a.p[]=;b.p[]=;a.num=;b.num=;
  59. for (i=;i<=n;i++)
  60. {
  61. c=add(a,b);
  62. a.num=b.num;for (j=;j<=a.num;j++) a.p[j]=b.p[j];
  63. b.num=c.num;for (j=;j<=b.num;j++) b.p[j]=c.p[j];
  64. }
  65. c=chen(c,c);
  66. for (i=c.num;i>;i--)
  67. printf("%d",c.p[i]);
  68. }
  69. return ;
  70. }

值得一做》关于数学与递推 BZOJ1002 (BZOJ第一页计划)(normal+)的更多相关文章

  1. 值得一做》关于一道DP+SPFA的题 BZOJ1003 (BZOJ第一页计划) (normal-)

    这是一道数据范围和评测时间水的可怕的题,只是思路有点难想,BUT假如你的思路清晰,完全了解怎么该做,那就算你写一个反LLL和反SLE都能A,如此水的一道题,你不心动吗? 下面贴出题目 Descript ...

  2. 值得一做》关于并查集的进化题目 BZOJ1015(BZOJ第一页计划)(normal-)

    这道题和以前做过的一道经典的洪水冲桥问题很像,主要做法是逆向思维.(BZOJ第10道非SB题纪念) 先给出题目 Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者 ...

  3. 2017"百度之星"程序设计大赛 - 复赛1003&&HDU 6146 Pokémon GO【数学,递推,dp】

    Pokémon GO Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  4. CF Gym 100187D Holidays (数学,递推)

    题意:给n个元素,从n中选两个非空集合A和B.问有多少中选法? 递推: dp[n]表示元素个数为n的方案数,对于新来的一个元素,要么加入集合,要么不加入集合自成一个集合.加入集合有三种选择,A,B,E ...

  5. 【递推】BZOJ 3930: [CQOI2015]选数

    Description 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公 ...

  6. 值得一做》关于双标记线段树两三事BZOJ 1798 (NORMAL-)

    这是一道双标记线段树的题,很让人很好的预习/学习/复习线段树,我不知道它能让别人学习什么,反正让我对线段树的了解更加深刻. 题目没什么好讲的,程序也没什么好讲的,所以也没有什么题解,但是值得一做 给出 ...

  7. UVa 10288 - Coupons(数学期望 + 递推)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  8. hdu 2190 重建希望小学(数学,递推)

    题意: N*3的教室,有2种砖,2*2.1*1. 问铺设教室的方案有多少种.(要铺满) 思路: 画一下图可以很快发现递推公式 代码: int main(){ int a[35]; mem(a,0); ...

  9. 【递推】BZOJ 4300:绝世好题

    4300: 绝世好题 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 564  Solved: 289[Submit][Status][Discuss] ...

随机推荐

  1. Sublime Text 3下Emmet使用技巧

    链接:http://jingyan.baidu.com/article/92255446a87900851648f4d6.html

  2. 剑指offer-第四章解决面试题思路(复杂链表的复制)

    题目:请写一个函数clone(ComplexListNode pHead),实现复杂链表的复制. 复杂链表的数据结构如下:public class ComplexListNode{int m_nVal ...

  3. Fragment详解及举例

    1.为什么用Fragment(Android3.0提出)来替代TabActivity(Android4.0以后正式被弃用)? 因为Fragment可以适应各种不同屏幕大小,也就是适应不同屏幕的分辨率. ...

  4. Hexo博客网站再配置

    这两天整理网站方面的事,本地IIS部署,个人网站,发现我的hexo做的个人网站实在很单调,于是找来资料做进一步的配置. 一.网站图标 看一下hexo\themes\modernist\layout\_ ...

  5. 实体对象,List泛型 转换为DataTable

    /// <summary>        /// 实体对象转换DataTable        /// </summary>        /// <param name ...

  6. 转载 eclipse中的include设置

    备注:在10.1版的niosii使用的eclipse中设置的方法是右键->properties->c/c++general->path and symbols->include ...

  7. java的日期加减

    在mysql里面

  8. Maven项目中突然找不到Build Path或maven dependencies library

    这两天发现有个maven项目抽风了,一个是右击项目找不到Build Path了,一个是依赖的lib库没了,maven引入的依赖包导不了.后来发现是eclipse搞的鬼,出问题的是项目下的.classp ...

  9. Linux Samba目录服务搭建与Java客户端访问

    前言: 本文比较简略,只求快速入门,若要了解详情,推荐一篇文章:http://www.cnblogs.com/mchina/archive/2012/12/18/2816717.html 1,安装sa ...

  10. 蓝桥杯 算法训练 ALGO-114 黑白无常

    算法训练 黑白无常   时间限制:1.0s   内存限制:256.0MB 问题描述 某寝室的同学们在学术完之后准备玩一个游戏:游戏是这样的,每个人头上都被贴了一张白色或者黑色的纸,现在每个人都会说一句 ...