1. 程式人生 > >UVA 10844 - Bloques (第二類斯特靈數)

UVA 10844 - Bloques (第二類斯特靈數)

pro 壓縮 i++ ring styles () sub comm show

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("\n"); } 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; }

UVA 10844 - Bloques (第二類斯特靈數)