好久好久好久好久没写博客了,由于csdn改版了,一直不大喜欢,所以也就不大乐意上博客了。。其实说起来也没什么题好写的,有时候还是会做到好题的,由于已经忘记了csdn忘记了我有博客,于是就没写了。but 现在还是继续开始吧,有什么感觉不错的题还是可以mark下的。
接下来是题意,中文题就是好,直接上题目。。
给定n(N<=100),编程计算有多少个不同的n轮状病毒。
思路:
题目就是求最小生成树的种数,中心的点必须要和周围的一圈点连通,可以先不要管环,先考虑链的情况
dp[ i ][ 0 ]表示第i个点还没和中心点连通,并且前i-1个点和中心点或者第i个点是连通的
dp[ i ][ 1 ]表示前i个点全部都已经和中心点连通了
很容易可以推出状态转移方程 :
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<
<