luogu P2144 [FJOI2007] 轮状病毒 矩阵(da)生成树(biao)+高精

传送门

明显的生成树

所以矩阵统计完全图的生成树计数就OK

......原地懵逼

并不会行列式

等等 完全图

果断列了一个矩阵(主对角线N*(N-1)/2,其他(N-1))

(当然是3*3矩阵和4*4矩阵)

然后搞了一个互相推

....30minutes later......

两个矩阵推不出来 试试三个

(当然是2,3,4)

....20minutes later......

发现满足f[n] = f[n-1] * 3 - f[n-2] + 2 (鬼知道我是怎么发现的)

1和2可以手胡

然后n<=100...int256都炸了吧

跪着写高精...

Time cost : 115min

(真要考试遇上这题不得godie)

Code:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<queue>
  5 #define ms(a,b) memset(a,b,sizeof a)
  6 #define rep(i,a,n) for(int i = a;i <= n;i++)
  7 #define per(i,n,a) for(int i = n;i >= a;i--)
  8 #define inf 1000000007
  9 using namespace std;
 10 typedef long long ll;
 11 typedef double D;
 12 #define eps 1e-8
 13 ll read() {
 14     ll as = 0,fu = 1;
 15     char c = getchar();
 16     while(c < ‘0‘ || c > ‘9‘) {
 17         if(c == ‘-‘) fu = -1;
 18         c = getchar();
 19     }
 20     while(c >= ‘0‘ && c <= ‘9‘) {
 21         as = as * 10 + c - ‘0‘;
 22         c = getchar();
 23     }
 24     return as * fu;
 25 }
 26 //head
 27
 28 struct Big {
 29     const static int N = 5005;
 30     int a[N];
 31     bool flag;
 32     Big(){}
 33     Big( ll x ){
 34         ms(a,0),flag = 0;
 35         flag = (x < 0);
 36         x = max(x,-x);
 37         while(x) a[++a[0]] = x%10,x/=10;
 38         clr0();
 39     }
 40     void read() {
 41         ms(a,0),flag = 0;
 42         char s[N];
 43         scanf("%s",s+1);
 44         a[0] = strlen(s+1);
 45         if(s[1] == ‘-‘) a[0]--,flag = 1;
 46         rep(i,1,a[0]) a[i] = s[a[0] - i + flag + 1] - ‘0‘;
 47         clr0();
 48     }
 49     void clr0() {
 50         while(a[0] && a[a[0]] == 0) a[0]--;
 51         while(a[0] < 0) a[0]++;
 52         if(a[0] == 0) flag = 0;
 53     }
 54     void print() {
 55         clr0();
 56         if(!a[0]) return void(puts("0"));
 57         if(flag) putchar(‘-‘);
 58         per(i,a[0],1) putchar(a[i] + ‘0‘);
 59         putchar(‘\n‘);
 60     }
 61     //clr0 before use
 62     bool operator < (const Big &o) const {
 63         if(o.a[0] == 0) return flag;
 64         if(a[0] == 0) return !o.flag;
 65         if(flag ^ o.flag) return flag;
 66         if(flag) {
 67             rep(i,0,a[0]) {
 68                 if(a[i] > o.a[i]) return 1;
 69                 if(a[i] < o.a[i]) return 0;
 70             }
 71             return 0;
 72         } else {
 73             rep(i,0,a[0]) {
 74                 if(a[i] < o.a[i]) return 1;
 75                 if(a[i] > o.a[i]) return 0;
 76             }
 77             return 0;
 78         }
 79     }
 80     bool operator == (const Big &o) const {
 81         Big r = *this;
 82         return !(r < o || o < r);
 83     }
 84     //保证同号
 85     Big operator + (const Big &o) const {
 86         if(a[0] == 0) return o;
 87         if(o.a[0] == 0) return *this;
 88         if(flag ^ o.flag) {
 89             Big x = *this,y = o;
 90             if(x.flag) {
 91                 x.flag = 0;
 92                 return y - x;
 93             }
 94             else {
 95                 y.flag = 0;
 96                 return x - y;
 97             }
 98         }
 99         Big ans;
100         ms(ans.a,0);
101         ans.a[0] = max(a[0],o.a[0]),ans.flag = flag;
102         rep(i,1,ans.a[0]) {
103             ans.a[i] += a[i] + o.a[i];
104             if(i == ans.a[0] && ans.a[i] >= 10) {
105                 ans.a[0]++;
106             }
107             ans.a[i+1] += ans.a[i] / 10;
108             ans.a[i] %= 10;
109         }
110         return ans;
111     }
112     //保证同号
113     Big operator - (const Big &o) const {
114         Big x = *this;
115         Big y = o;
116         if(flag ^ o.flag) {
117             y.flag ^= 1;
118             return x + y;
119         }
120         Big ans;
121         ms(ans.a,0);
122         ans.a[0] = ans.flag = 0;
123         ans.flag = flag;
124         x.flag = y.flag = 0;
125         if(x == y) return ans;
126         if(x < y) swap(x,y),ans.flag ^= 1;
127         rep(i,1,x.a[0]) {
128             if(x.a[i] < y.a[i]) x.a[i] += 10,x.a[i+1]--;
129             ans.a[i] = x.a[i] - y.a[i];
130         }
131         ans.a[0] = x.a[0];
132         ans.clr0();
133         return ans;
134     }
135     //O(n^2) 高精乘
136     Big operator * (const Big &o) const {
137         if(a[0] == 0) return *this;
138         if(o.a[0] == 0) return o;
139         Big ans;
140         ms(ans.a,0);
141         ans.a[0] = a[0] + o.a[0],ans.flag = o.flag ^ flag;
142         rep(i,1,a[0]) rep(j,1,o.a[0])
143             ans.a[i+j-1] += a[i] * o.a[j];
144         rep(i,1,ans.a[0]) {
145             if(i == ans.a[0] && ans.a[i] >= 10) ans.a[0]++;
146             ans.a[i+1] += ans.a[i] / 10;
147             ans.a[i] %= 10;
148         }
149         return ans;
150     }
151 }x,y,z;
152 Big zero = Big(0);
153 Big one = Big(1);
154 Big two = Big(2);
155 Big three = Big(3);
156 void tst() {
157     while(1) {
158         x.read(),y.read();
159         z = x + y;
160         printf("plus:"),z.print();
161         z = x - y;
162         printf("minus:"),z.print();
163         z = x * y;
164         printf("mult:"),z.print();
165     }
166 }
167
168 #define Max(a,b) ((b)>(a)?(a):(b))
169 #define Min(a,b) ((a)<(b)?(a):(b))
170 int n,m;
171 const int N = 105;
172 Big f[N];
173
174 int main() {
175     n = read();
176     f[1] = one;
177     f[2] = Big(5);
178     rep(i,3,n) f[i] = three * f[i-1] - f[i-2] + two;
179     f[n].print();
180     return 0;
181 }

原文地址:https://www.cnblogs.com/yuyanjiaB/p/9901200.html

时间: 2024-11-09 17:14:53

luogu P2144 [FJOI2007] 轮状病毒 矩阵(da)生成树(biao)+高精的相关文章

bzoj 1002 [FJOI2007]轮状病毒 高精度&amp;&amp;找规律&amp;&amp;基尔霍夫矩阵

1002: [FJOI2007]轮状病毒 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2234  Solved: 1227[Submit][Status] Description 给定n(N<=100),编程计算有多少个不同的n轮状病毒. Input 第一行有1个正整数n. Output 将编程计算出的不同的n轮状病毒数输出 Sample Input 3 Sample Output 16 HINT Source 基尔霍夫矩阵总算编出来了,这道题考

BZOJ 1002: [FJOI2007]轮状病毒 递推/基尔霍夫矩阵树定理

f[n]=3*f[n-1]-f[n-2]+2 1002: [FJOI2007]轮状病毒 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 2959  Solved: 1644 [Submit][Status][Discuss] Description 给定n(N<=100),编程计算有多少个不同的n轮状病毒. Input 第一行有1个正整数n. Output 将编程计算出的不同的n轮状病毒数输出 Sample Input 3 Sample Outpu

洛谷 P2144 BZOJ 1003 [FJOI2007]轮状病毒

题目描述 轮状病毒有很多变种.许多轮状病毒都是由一个轮状基产生.一个n轮状基由圆环上n个不同的基原子和圆心的一个核原子构成.2个原子之间的边表示这2个原子之间的信息通道,如图1. n轮状病毒的产生规律是在n轮状基中删除若干边,使各原子之间有唯一一条信息通道.例如,共有16个不同的3轮状病毒,入图2所示. 给定n(N<=100),编程计算有多少个不同的n轮状病毒. 输入输出格式 输入格式: 第一行有1个正整数n. 输出格式: 将编程计算出的不同的n轮状病毒数输出 输入输出样例 输入样例#1: 3

BZOJ 1002 [FJOI2007]轮状病毒

1002: [FJOI2007]轮状病毒 Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道.如下图所示 N轮状病毒的产生规律是在一个N轮状基中删去若干条边,使得各原子之间有唯一的信息通道,例如共有16个不同的3轮状病毒,如下图所示 现给定n(N<=100),编程计算有多少个不同的n轮状病毒 Input 第一行有1个正整数n Output 计算出的不同的n

bzoj1002[FJOI2007]轮状病毒

bzoj1002[FJOI2007]轮状病毒 题意: N轮状病毒的产生规律是在一个N轮状基中删去若干条边,使得各原子之间有唯一的信息通道,例如共有16个不同的3轮状病毒,如下图所示 现给定n,计算有多少个不同的n轮状病毒.N<=100 题解: 公式:f[i]=f[i-1]*3-f[i-2]+2,i≥3,f[1]=1,f[2]=5.(我承认我是抄的QAQ因为我根本不懂什么矩阵树定理~ 又是高精度,又被我用python水掉了…… 代码: 1 n=int(raw_input()) 2 a=1 3 b=

1002: [FJOI2007]轮状病毒

1002: [FJOI2007]轮状病毒 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2609  Solved: 1450[Submit][Status] Description 给定n(N<=100),编程计算有多少个不同的n轮状病毒. Input 第一行有1个正整数n. Output 将编程计算出的不同的n轮状病毒数输出 Sample Input 3 Sample Output 16 HINT Source 题解:这道题可以采用“打表—找规律

[FJOI2007]轮状病毒 题解(dp(找规律)+高精度)

[FJOI2007]轮状病毒 题解(dp(找规律)+高精度) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1335733 没什么好说的,直接把规律找出来,有两种规律(据说还有多种dp),再套个高精度 \(First\) \(f[1]=1,f[2]=5,f[i]=3×f[i-1]-f[i-2]+2\) 就直接写个高精+低精和高精×低精和高精-高精就行了 \(Second\) \(f[1]=1,f[2]=3,f[i]=f[i-1]+f[i-2]\) \(i

BZOJ_1002_[FJOI2007]_轮状病毒(递推+高精)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1002 )*&*(^&*^&*^**()*) 分析 题目是求一种特殊的图的生成树的个数,但是貌似有更一般的算法,等明天再看吧... 只搞懂了打表找规律,然后题推的解法. 随便写个暴力打个表(其实我并不会写,明天再写吧今天好累),找一找规律. 1~14的答案如下 1 5 16 45 121 320 841 2205 5776 15125 39601 103680 271441 71

【日常学习】【区间DP+高精】codevs1166 矩阵取数游戏题解

题目来自NOIP2007TG3 如果在考场上我现在已经歇菜了吧 今天一整天的时间全部投在这道题上,收获不小. 先上题目 题目描述 Description [问题描述] 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均 为非负整数.游戏规则如下: 1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. 每次取走的各个元素只能是该元素所在行的行首或行尾: 3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素