UVa Problem Solution: 10198 - Counting
2008-11-27 16:36
561 查看
Let f(n) denote the number of ways to make the sum of n. When n > 3, the number of digits is greater than 1. The first digit d used must be one of 1, 2, 3 or 4. Remove the first digit, then the remaining sum is n-d. There are f(n-d) ways to make the sum of n-d, so we've found the recurrence of
f(n) = 2*f(n-1) + f(n-2) + f(n-3)
and the base cases are
f(1) = 2, f(2) = 5, f(3) = 13
Code:
/*************************************************************************
* Copyright (C) 2008 by liukaipeng *
* liukaipeng at gmail dot com *
*************************************************************************/
/* @JUDGE_ID 00000 10198 C++ "Counting" */
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <deque>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
struct bignum
{
bignum(int v = 0) : start(max_digits)
{
bzero(digits, max_digits);
assign(v);
}
bignum(char const *v) : start(max_digits)
{
bzero(digits, max_digits);
assign(v);
}
void assign(int v)
{
start = max_digits;
for (; v != 0; v /= 10) digits[--start] = v % 10;
}
void assign(char const *v)
{
start = max_digits - strlen(v);
for (int i = start; i < max_digits; ++i)
digits[i] = *v++ - '0';
remove_leading_zero();
}
void convert(int& v) const
{
v = 0;
for (int i = start; i < max_digits; ++i, v *= 10) v += digits[i];
}
void convert(char *v) const
{
for (int i = start; i < max_digits; ++i)
*v++ = digits[i] + '0';
*v = '/0';
}
bignum& operator+=(bignum const& other)
{
start = min(start, other.start) - 1;
for (int i = max_digits - 1, carry = 0; i >= start; --i) {
int s = digits[i] + other.digits[i] + carry;
digits[i] = s % 10;
carry = s / 10;
}
remove_leading_zero();
return *this;
}
bignum operator+(bignum const& other) const
{
bignum tmp(*this);
tmp += other;
return tmp;
}
bool operator<(bignum const& other) const
{
if (start > other.start) return true;
else if (start < other.start) return false;
return memcmp(digits + start, other.digits + start, max_digits - start) < 0;
}
static int const max_digits = 500;
char digits[max_digits];
int start;
private:
void remove_leading_zero()
{
for (; digits[start] == 0 && start < max_digits; ++start) {}
}
};
inline istream& operator>>(istream& is, bignum& n)
{
char buf[bignum::max_digits+1];
is >> buf;
n.assign(buf);
return is;
}
inline ostream& operator<<(ostream& os, bignum const& n)
{
char buf[bignum::max_digits+1];
n.convert(buf);
os << buf;
return os;
}
/*
* Let f(n) denote the number of ways to make the sum of n. When n > 3, the number
* of digits is greater than 1. The first digit d used must be one of 1, 2, 3 or 4.
* Remove the first digit, then the remaining sum is n-d. There are f(n-d) ways to
* make the sum of n-d, so we've found the recurrence of
* f(n) = 2*f(n-1) + f(n-2) + f(n-3)
* and the base cases are
* f(1) = 2, f(2) = 5, f(3) = 13
*/
void gen_numbers(bignum *numbers, int size)
{
numbers[1] = 2;
numbers[2] = 5;
numbers[3] = 13;
for (int i = 4; i < size; ++i) {
numbers[i] = numbers[i-1] + numbers[i-1];
numbers[i] += numbers[i-2];
numbers[i] += numbers[i-3];
}
}
int main(int argc, char *argv[])
{
#ifndef ONLINE_JUDGE
freopen((string(argv[0]) + ".in").c_str(), "r", stdin);
freopen((string(argv[0]) + ".out").c_str(), "w", stdout);
#endif
int const size = 1001;
bignum numbers[size];
gen_numbers(numbers, size);
for (int n; cin >> n; ) cout << numbers
<< '/n';
return 0;
}
f(n) = 2*f(n-1) + f(n-2) + f(n-3)
and the base cases are
f(1) = 2, f(2) = 5, f(3) = 13
Code:
/*************************************************************************
* Copyright (C) 2008 by liukaipeng *
* liukaipeng at gmail dot com *
*************************************************************************/
/* @JUDGE_ID 00000 10198 C++ "Counting" */
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <deque>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
struct bignum
{
bignum(int v = 0) : start(max_digits)
{
bzero(digits, max_digits);
assign(v);
}
bignum(char const *v) : start(max_digits)
{
bzero(digits, max_digits);
assign(v);
}
void assign(int v)
{
start = max_digits;
for (; v != 0; v /= 10) digits[--start] = v % 10;
}
void assign(char const *v)
{
start = max_digits - strlen(v);
for (int i = start; i < max_digits; ++i)
digits[i] = *v++ - '0';
remove_leading_zero();
}
void convert(int& v) const
{
v = 0;
for (int i = start; i < max_digits; ++i, v *= 10) v += digits[i];
}
void convert(char *v) const
{
for (int i = start; i < max_digits; ++i)
*v++ = digits[i] + '0';
*v = '/0';
}
bignum& operator+=(bignum const& other)
{
start = min(start, other.start) - 1;
for (int i = max_digits - 1, carry = 0; i >= start; --i) {
int s = digits[i] + other.digits[i] + carry;
digits[i] = s % 10;
carry = s / 10;
}
remove_leading_zero();
return *this;
}
bignum operator+(bignum const& other) const
{
bignum tmp(*this);
tmp += other;
return tmp;
}
bool operator<(bignum const& other) const
{
if (start > other.start) return true;
else if (start < other.start) return false;
return memcmp(digits + start, other.digits + start, max_digits - start) < 0;
}
static int const max_digits = 500;
char digits[max_digits];
int start;
private:
void remove_leading_zero()
{
for (; digits[start] == 0 && start < max_digits; ++start) {}
}
};
inline istream& operator>>(istream& is, bignum& n)
{
char buf[bignum::max_digits+1];
is >> buf;
n.assign(buf);
return is;
}
inline ostream& operator<<(ostream& os, bignum const& n)
{
char buf[bignum::max_digits+1];
n.convert(buf);
os << buf;
return os;
}
/*
* Let f(n) denote the number of ways to make the sum of n. When n > 3, the number
* of digits is greater than 1. The first digit d used must be one of 1, 2, 3 or 4.
* Remove the first digit, then the remaining sum is n-d. There are f(n-d) ways to
* make the sum of n-d, so we've found the recurrence of
* f(n) = 2*f(n-1) + f(n-2) + f(n-3)
* and the base cases are
* f(1) = 2, f(2) = 5, f(3) = 13
*/
void gen_numbers(bignum *numbers, int size)
{
numbers[1] = 2;
numbers[2] = 5;
numbers[3] = 13;
for (int i = 4; i < size; ++i) {
numbers[i] = numbers[i-1] + numbers[i-1];
numbers[i] += numbers[i-2];
numbers[i] += numbers[i-3];
}
}
int main(int argc, char *argv[])
{
#ifndef ONLINE_JUDGE
freopen((string(argv[0]) + ".in").c_str(), "r", stdin);
freopen((string(argv[0]) + ".out").c_str(), "w", stdout);
#endif
int const size = 1001;
bignum numbers[size];
gen_numbers(numbers, size);
for (int n; cin >> n; ) cout << numbers
<< '/n';
return 0;
}
相关文章推荐
- UVa Problem 10198 Counting (数数)
- UVA 1640 The Counting Problem UVA1640 求[a,b]或者[b,a]区间内0~9在里面各个数的数位上出现的总次数。
- UVa Problem Solution: 10196 - Check The Check
- UVa Problem Solution: 10149 - Yahtzee
- UVa Problem Solution: 850 - Crypt Kicker II
- UVa Problem Solution: 120 - Stacks of Flapjacks
- UVa Problem Solution: 701 - The Archaeologist's Dilemma
- UVa Problem Solution: 10254 - The Priest Mathematician
- UVa Problem Solution: 10168 - Summation of Four Primes
- UVA 10516 Another Counting Problem
- Problem 009——UVa 1225 - Digit Counting
- UVa Problem Solution: 100 - The 3n+1 problem
- UVa Problem Solution: 10142 - Australian Voting
- UVa Problem Solution: 10082 - WERTYU
- UVa Problem Solution: 10188 - Automated Judge Script
- UVa Problem Solution: 10037 - Bridge
- UVa Problem Solution: 10152 - ShellSort
- UVa Problem Solution: 10127 - Ones
- UVa Problem Solution: 10006 - Carmichael Numbers
- UVa Problem Solution: 10042 - Smith Numbers