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<

posted @ 2019-05-16 14:01  mqxnongmin  阅读(103)  评论(0编辑  收藏  举报