分析:把”已经使用过的火柴数i”看成状态,可以得到一个图。从前往后每添加一个数字x,就从状态i转移到i+c[x],其中c[x]代表数字x需要的火柴数。当i=0的时候不允许
使用数字0(最后当n>=6时,给答案单独加上1,代表整数0)。
令d(i)为从结点0到结点i的路径条数,则答案f(n)=d(1)+d(2)+d(3)+...+d(n)(因为火柴不必用完,所以使用的火柴的数目可能是1,2,3,...,n)。
程序实现时,我们可以按照从小到大的顺序用d(i)更新所有的d(i+c[j])(j取遍数字0~9),
这道题思路难度是状态转移,而编码难度在大数加法,好久没写大数加法,又有些生疏了,贴上代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define LL long long
const int MAXN=505;
const int N=2005;
struct bign{
int len,num[MAXN];
bign ()
{
len=0;
memset(num,0,sizeof(num));
}
bign (int number)
{
*this=number;
}
void DelZero()
{
while(len&&num[len-1]==0)
{
len--;
}
if(len==0)
num[len++]=0;
}
void put()
{
for(int i=len-1;i>=0;i--)
cout<<num[i];
}
bign operator +(const bign &b)
{
int bigsum=0;
bign ans;
for(int i=0;i<len||i<b.len;i++)
{
if(i<len) bigsum+=num[i];
if(i<b.len) bigsum+=b.num[i];
ans.num[ans.len++]=bigsum%10;
bigsum/=10;
}
while(bigsum)
{
ans.num[ans.len++]=bigsum%10;
bigsum/=10;
}
return ans;
}
void operator =(int number)
{
len=0;
while(number)
{
num[len++]=number%10;
number/=10;
}
DelZero();
}
bign operator +(const int &b)
{
bign a = b;
return *this+a;
}
};
bign dp[N];
const int c[20]={6,2,5,5,4,5,6,3,7,6};
int main()
{
memset(dp,0,sizeof(dp));
dp[0]=1;
dp[1]=0;
for(int i=0;i<=2000;i++)
for(int j=0;j<10;j++)
{
if(i==0&&j==0)
continue;
if(i+c[j]<=2000)
dp[i+c[j]]=dp[i+c[j]]+dp[i];
}
dp[6]=dp[6]+1;
for(int i=2;i<=2000;i++)
dp[i]=dp[i]+dp[i-1];
int n;
while(cin>>n)
{
dp[n].put();
cout<<endl;
}
return 0;
}
下面贴上大数的其他运算:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int MAXN = 505;
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 = 2005;
const int c[20] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6};
bign dp[N];
int main () {
dp[0] = 1;
dp[1] = 0;
for (int i = 0; i <= 2000; i++) {
for (int j = 0; j < 10; j++) {
if (i == 0 && j == 0)
continue;
if (i + c[j] <= 2000)
dp[i+c[j]] = dp[i+c[j]] + dp[i];
}
}
dp[6] = dp[6] + 1;
for (int i = 2; i <= 2000; i++)
dp[i] = dp[i] + dp[i-1];
int n;
while (scanf("%d", &n) == 1 && n > 0) {
dp[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 () {
for (int i = len-1; i >= 0; i--)
printf("%d", 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 % 10;
bignSum /= 10;
}
while (bignSum) {
ans.num[ans.len++] = bignSum % 10;
bignSum /= 10;
}
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;
}