• UVA 10844


    UVA 10844 - Bloques

    题目链接

    题意:给定n个数字,问这n个数字能分成子集分成有几种分法
    思路:一開始先想了个状态。dp[i][j]表示放i个数字,分成j个集合的方案,那么转移为,从dp[i - 1][j - 1]在多一个集合。和从dp[i - 1][j]有j个位置放,那么转移方程为dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j] * j;按理说这个状态转移是没问题的。可是因为这题答案是高精度,n为900时答案高达1700多位。加上高精度运算结果就超时了,后面知道这样的是bell数。是能够通过杨辉三角推出来的。详细就是一个数字等于杨辉三角的左边和左上边相加,这样状态转移变成纯高精度加法,然后把高精度加法运算进行压缩位的高精度运算,勉强通过了
    代码:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    using namespace std;
    const int MAXN = 1800;
    
    struct bign {
        int len, num[MAXN];
    
        bign () {
        len = 0;
        memset(num, 0, sizeof(num));
        }
        bign (int number) {*this = number;}
        bign (const char* number) {*this = number;}
    
        void DelZero ();
        void Put ();
    
        void operator = (int number);
        void operator = (char* number);
    
        bool operator <  (const bign& b) const;
        bool operator >  (const bign& b) const { return b < *this; }
        bool operator <= (const bign& b) const { return !(b < *this); }
        bool operator >= (const bign& b) const { return !(*this < b); }
        bool operator != (const bign& b) const { return b < *this || *this < b;}
        bool operator == (const bign& b) const { return !(b != *this); }
    
        void operator ++ ();
        void operator -- ();
        bign operator + (const int& b);
        bign operator + (const bign& b);
        bign operator - (const int& b);
        bign operator - (const bign& b);
        bign operator * (const int& b);
        bign operator * (const bign& b);
        bign operator / (const int& b);
        //bign operator / (const bign& b);
        int operator % (const int& b);
    };
    
    /*Code*/
    
    const int N = 905;
    int n;
    bign dp[2][N], ans[N];
    
    void init() {
        int pre = 1, now = 0;
        dp[now][1] = 1; ans[1] = 1;
        for (int i = 2; i <= 900; i++) {
        swap(now, pre);
        dp[now][1] = dp[pre][i - 1];
        for (int j = 2; j <= i; j++)
            dp[now][j] = dp[now][j - 1] + dp[pre][j - 1];
        ans[i] = dp[now][i];
        }
    }
    
    int main() {
        init();
        while (~scanf("%d", &n) && n) {
        printf("%d, ", n);
        ans[n].Put(); printf("
    ");
        }
        return 0;
    }
    
    void bign::DelZero () {
        while (len && num[len-1] == 0)
        len--;
    
        if (len == 0) {
        num[len++] = 0;
        }
    }
    
    void bign::Put () {
        printf("%d", num[len - 1]);
        for (int i = len-2; i >= 0; i--) 
        printf("%08d", num[i]);
    }
    
    void bign::operator = (char* number) {
        len = strlen (number);
        for (int i = 0; i < len; i++)
        num[i] = number[len-i-1] - '0';
    
        DelZero ();
    }
    
    void bign::operator = (int number) {
    
        len = 0;
        while (number) {
        num[len++] = number%10;
        number /= 10;
        }
    
        DelZero ();
    }
    
    bool bign::operator < (const bign& b) const {
        if (len != b.len)
        return len < b.len;
        for (int i = len-1; i >= 0; i--)
        if (num[i] != b.num[i])
            return num[i] < b.num[i];
        return false;
    }
    
    void bign::operator ++ () {
        int s = 1;
    
        for (int i = 0; i < len; i++) {
        s = s + num[i];
        num[i] = s % 10;
        s /= 10;
        if (!s) break;
        }
    
        while (s) {
        num[len++] = s%10;
        s /= 10;
        }
    }
    
    void bign::operator -- () {
        if (num[0] == 0 && len == 1) return;
    
        int s = -1;
        for (int i = 0; i < len; i++) {
        s = s + num[i];
        num[i] = (s + 10) % 10;
        if (s >= 0) break;
        }
        DelZero ();
    }
    
    bign bign::operator + (const int& b) {
        bign a = b;
        return *this + a;
    }
    
    bign bign::operator + (const bign& b) {
        int bignSum = 0;
        bign ans;
    
        for (int i = 0; i < len || i < b.len; i++) {
        if (i < len) bignSum += num[i];
        if (i < b.len) bignSum += b.num[i];
    
        ans.num[ans.len++] = bignSum % 100000000;
        bignSum /= 100000000;
        }
    
        while (bignSum) {
        ans.num[ans.len++] = bignSum % 100000000;
        bignSum /= 100000000;
        }
    
        return ans;
    }
    
    bign bign::operator - (const int& b) {
        bign a = b;
        return *this - a;
    }
    
    
    bign bign::operator - (const bign& b) {
        int bignSub = 0;
        bign ans;
        for (int i = 0; i < len || i < b.len; i++) {
        bignSub += num[i];
        bignSub -= b.num[i];
        ans.num[ans.len++] = (bignSub + 10) % 10;
        if (bignSub < 0) bignSub = -1;
        }
        ans.DelZero ();
        return ans;
    }
    
    bign bign::operator * (const int& b) {
        int bignSum = 0;
        bign ans;
    
        ans.len = len;
        for (int i = 0; i < len; i++) {
        bignSum += num[i] * b;
        ans.num[i] = bignSum % 10;
        bignSum /= 10;
        }
    
        while (bignSum) {
        ans.num[ans.len++] = bignSum % 10;
        bignSum /= 10;
        }
    
        return ans;
    }
    
    bign bign::operator * (const bign& b) {
        bign ans;
        ans.len = 0; 
    
        for (int i = 0; i < len; i++){  
        int bignSum = 0;  
    
        for (int j = 0; j < b.len; j++){  
            bignSum += num[i] * b.num[j] + ans.num[i+j];  
            ans.num[i+j] = bignSum % 10;  
            bignSum /= 10;
        }  
        ans.len = i + b.len;  
    
        while (bignSum){  
            ans.num[ans.len++] = bignSum % 10;  
            bignSum /= 10;
        }  
        }  
        return ans;
    }
    
    bign bign::operator / (const int& b) {
    
        bign ans;
    
        int s = 0;
        for (int i = len-1; i >= 0; i--) {
        s = s * 10 + num[i];
        ans.num[i] = s/b;
        s %= b;
        }
    
        ans.len = len;
        ans.DelZero ();
        return ans;
    }
    
    int bign::operator % (const int& b) {
    
        bign ans;
    
        int s = 0;
        for (int i = len-1; i >= 0; i--) {
        s = s * 10 + num[i];
        ans.num[i] = s/b;
        s %= b;
        }
    
        return s;
    }
  • 相关阅读:
    TcpClient连接帮助类
    winform中添加管理员权限控制
    textbox中输入email做格式控制
    绑定和非绑定方法
    类的封装、property、多态和多态性
    继承类之点点滴滴
    爬虫日记-正则表达式
    爬虫日记-单元总结
    爬虫日记-最好大学排名实例
    爬虫日记-第一单元总结
  • 原文地址:https://www.cnblogs.com/mqxnongmin/p/10802146.html
Copyright © 2020-2023  润新知