1 条题解
-
1
using namespace std; // 高精度整数:十进制 1e9 进制,小端存储 struct BigInt { vector<int> d; BigInt() : d(1, 0) {} BigInt(int x) { if (x == 0) d.push_back(0); else { while (x) { d.push_back(x % 1000000000); x /= 1000000000; } } } void trim() { while (d.size() > 1 && d.back() == 0) d.pop_back(); } BigInt operator+(const BigInt& o) const { BigInt r; r.d.assign(max(d.size(), o.d.size()) + 1, 0); long long carry = 0; for (size_t i = 0; i < r.d.size(); i++) { long long s = carry; if (i < d.size()) s += d[i]; if (i < o.d.size()) s += o.d[i]; r.d[i] = (int)(s % 1000000000); carry = s / 1000000000; } r.trim(); return r; } // 前提:*this >= o BigInt operator-(const BigInt& o) const { BigInt r; r.d.assign(d.size(), 0); long long borrow = 0; for (size_t i = 0; i < d.size(); i++) { long long s = (long long)d[i] - borrow - (i < o.d.size() ? o.d[i] : 0); if (s < 0) { s += 1000000000; borrow = 1; } else borrow = 0; r.d[i] = (int)s; } r.trim(); return r; } void print() const { printf("%d", d.back()); for (int i = (int)d.size() - 2; i >= 0; i--) printf("%09d", d[i]); printf("\n"); } }; int main() { int k, w; scanf("%d%d", &k, &w); int B = 1 << k; // 2^k(k<=9,B<=512) int n = w / k, m = w % k; // 递推杨辉三角,只需保留上一行;快照第 B-1 行与第 B-2^m 行 vector<BigInt> prev(1, BigInt(1)), rowB1, rowBmin; for (int top = 0; top <= B - 1; top++) { vector<BigInt> cur(top + 1, BigInt(0)); cur[0] = BigInt(1); for (int j = 1; j <= top; j++) cur[j] = prev[j - 1] + (j < (int)prev.size() ? prev[j] : BigInt(0)); if (top == B - 1) rowB1 = cur; if (m > 0 && top == B - (1 << m)) rowBmin = cur; prev = move(cur); } BigInt ans; for (int d = 2; d <= min(n, B - 1); d++) ans = ans + rowB1[d]; if (m > 0) { // 补上 d = n+1 位的贡献:C(B-1, n+1) - C(B-2^m, n+1) BigInt a = (n + 1 <= B - 1) ? rowB1[n + 1] : BigInt(0); BigInt b = (n + 1 <= B - (1 << m)) ? rowBmin[n + 1] : BigInt(0); ans = ans + (a - b); } ans.print(); return 0; }
- 1
信息
- ID
- 690
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 10
- 标签
- 递交数
- 8
- 已通过
- 2
- 上传者