BZOJ 1002: [FJOI2007]轮状病毒
好久好久好久好久没写博客了,因为csdn改版了,一直不大喜欢,所以也就不大乐意上博客了。
。事实上说起来也没什么题好写的,有时候还是会做到好题的。因为已经忘记了csdn忘记了我有博客,于是就没写了。
but 如今还是继续開始吧,有什么感觉不错的题还是能够mark下的。
接下来是题意,中文题就是好,直接上题目。
。
给定n(N<=100),编程计算有多少个不同的n轮状病毒。
思路:
题目就是求最小生成树的种数。中心的点必需要和周围的一圈点连通。能够先不要管环,先考虑链的情况
dp[ i ][ 0 ]表示第i个点还没和中心点连通,而且前i-1个点和中心点或者第i个点是连通的
dp[ i ][ 1 ]表示前i个点所有都已经和中心点连通了
非常easy能够推出状态转移方程 :
dp[ i ][ 0 ] = dp[ i-1 ][ 0 ] + dp[ i-1 ][ 1 ]
dp[ i ][ 1 ] = dp[ i-1 ][ 0 ] + dp[ i-1 ][ 1 ]*2
那么对于n轮状病毒。能够枚举第一个点和多少个周围的点连通,其余的点就是一条链的情况了。
ps: 高精度是必须的
code:
#include
#include
#include
#include
#include
using namespace std;
const int numlen = 205;
struct bign {
int len, s[numlen];
bign(){
memset(s, 0, sizeof(s));
len = 1;
}
bign(int num) { *this = num; }
bign(const char *num) { *this = num; }
bign operator = (const int num) {
char s[numlen];
sprintf(s, "%d", num);
*this = s;
return *this;
}
bign operator = (const char *num) {
len = strlen(num);
while(len > 1 && num[0] == '0') num++, len--;
for(int i = 0;i < len; i++) s[i] = num[len-i-1] - '0';
return *this;
}
void deal() {
while(len > 1 && !s[len-1]) len--;
}
bign operator + (const bign &a)const {
bign ret ;
ret.len = 0;
int top = max(len, a.len), add = 0;
for(int i = 0;add || i < top; i++) {
int now = add;
if(i < len) now += s[i];
if(i < a.len) now += a.s[i];
ret.s[ret.len++] = now%10;
add = now/10;
}
return ret;
}
bign operator *(const int num) const {
bign ret;
ret.len = 0;
int bb = 0;
for(int i = 0;i < len; i++) {
int now = bb + s[i]*num;
ret.s[ret.len++] = now%10;
bb = now/10;
}
while(bb) {
ret.s[ret.len++] = bb%10;
bb /= 10;
}
ret.deal();
return ret;
}
string str() const {
string ret = "";
for(int i = 0;i < len; i++) ret = char(s[i]+'0') + ret;
return ret;
}
};
istream& operator >> (istream &in, bign &x) {
string s;
in >> s;
x = s.c_str();
return in;
}
ostream& operator << (ostream &out, const bign &x) {
out << x.str();
return out;
}
const int N = 100+5;
bign dp[N][2], ans[N];
void init(int n) {
dp[0][1] = 1;
dp[1][1] = dp[1][0] = 1; // 0: 表示未连接好的 1: 表示为连接好的
for(int i = 2;i <= n; i++) {
dp[i][1] = dp[i-1][0] + dp[i-1][1]*2;
dp[i][0] = dp[i-1][0] + dp[i-1][1];
}
for(int i = 1;i <= n; i++) {
ans[i] = 0;
for(int j = 1;j <= i; j++) {
ans[i] = ans[i] + dp[i-j][1]*j*j;
}
}
}
int main(){
int n;
scanf("%d", &n);
init(n);
cout<