描述
http://www.lydsy.com/JudgeOnline/problem.php?id=1002
)*&*(^&*^&*^**()*)
1002: [FJOI2007]轮状病毒
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 4060 Solved: 2239
[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
分析
题目是求一种特殊的图的生成树的个数,但是貌似有更一般的算法,等明天再看吧...
只搞懂了打表找规律,然后题推的解法.
随便写个暴力打个表(其实我并不会写,明天再写吧今天好累),找一找规律.
1~14的答案如下
1 5 16 45 121 320 841 2205 5776 15125 39601 103680 271441 710645
奇数项
1 16 121 841 5776 39601 271441
开根号得
1 4 11 29 76 199 521
a[i]=a[i-1]*3-a[i-2]
偶数项
5 45 320 2205 15125 103680 710645
除以5得
1 9 64 441 3025 20736 142129
开根号得
1 3 8 21 55 144 377
a[i]=a[i-1]*3-a[i-2]
注意要用高精(学习了别人的高精写法,自己写得太小学生了)
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
struct Big_Integer{
int x[],cnt;
int & operator [] (int id){
return x[id];
}
void operator = (int y){
x[]=y;
cnt=;
}
}f[];
Big_Integer operator - (Big_Integer x,Big_Integer y){
Big_Integer z=f[];
z.cnt=max(x.cnt,y.cnt);
for(int i=;i<=z.cnt;i++){
z[i]+=x[i]-y[i];
if(z[i]<) z[i+]--, z[i]+=;
}
while(z.cnt&&!z[z.cnt]) z.cnt--;
return z;
}
Big_Integer operator * (Big_Integer x,Big_Integer y){
Big_Integer z=f[];
for(int i=;i<=x.cnt;i++){
for(int j=;j<=y.cnt;j++){
z[i+j-]+=x[i]*y[j],z[i+j]+=z[i+j-]/,z[i+j-]%=;
}
}
z.cnt=x.cnt+y.cnt;
if(!z[z.cnt]) z.cnt--;
return z;
}
Big_Integer operator * (Big_Integer x,int y){
Big_Integer z=f[];
for(int i=;i<=x.cnt;i++){
z[i]+=x[i]*y,z[i+]+=z[i]/,z[i]%=;
}
z.cnt=x.cnt;
if(z[z.cnt+]) z.cnt++;
return z;
}
ostream& operator << (ostream &out,Big_Integer x){
for(int i=x.cnt;i;i--){
out << x[i];
}
return out;
}
int n;
int main(){
cin >> n;
f[]=;
f[]=n&?:;
int last=n+>>;
for(int i=;i<=last;i++){
f[i]=f[i-]*-f[i-];
}
cout << f[last]*f[last]*(n&?:) << endl;
return ;
}