题目链接
https://vjudge.net/problem/UVA-11375\
题意
用n根火柴能组成多少个非负整数,火柴不必用完。
分析
分析状态转移注意到,这个状态并不是随着火柴的增加,非负整数明显的随着变化。而是随着整数的位数增加有明显的状态转移。
设d(i)表示用完i根火柴所能组成的非负整数的个数,d(j)这个状态可以由任意d[i]加一个整数x得来,只要j=i+c[x].其中c[x]表示组成整数x所需火柴数。
这就是一个简单的递推了。
代码
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=2e3+100;
ll c[10]={6,2,5,5,4,5,6,3,7,6};
struct high
{
ll p[500],len;
high()
{
memset(p,0,sizeof(p));
len=0;
}
high(string s)
{
len=s.size();
reverse(s.begin(),s.end());
for(int i=0;i<len;i++)
p[i]=s[i]-'0';
}
high operator + (const high& o)const
{
high ans;
ans.len=max(len,o.len);
for(int i=0;i<ans.len;i++)
{
ans.p[i]+=p[i]+o.p[i];
ans.p[i+1]=ans.p[i]/10;
ans.p[i]%=10;
}
if(ans.p[ans.len]>0) ans.len++;
return ans;
}
high operator+=(const high& o)
{
*this=*this+o;
return *this;
}
void out()
{
if(len==0) putchar('0');
else
{
for(ll i=len-1;i>=0;i--)
printf("%d",p[i]);
}
putchar(10);
}
}d[maxn];
int main()
{
ios::sync_with_stdio(false);
ll n;
d[0]=high("1");
for(ll i=0;i<maxn;i++)
for(ll j=0;j<10;j++)
{
if(i==0&&j==0) continue;
if(i+c[j]<maxn)
d[i+c[j]]+=d[i];
}
d[6]+=high("1");
for(ll i=2;i<maxn;i++)
d[i]=d[i-1]+d[i];
while(cin>>n)
{
d[n].out();
}
return 0;
}