We can makedigits with matches as shown below: Given N matches, find the number ofdifferent numbers representable using the matches. We shall only make numbersgreater than or equal to 0, so no negative signs should be used. For instance,if you have 3 matches, then you can only make the numbers 1 or 7. If you have 4matches, then you can make the numbers 1, 4, 7 or 11. Note that leading zeros arenot allowed (e.g. 001, 042, etc. are illegal). Numbers such as 0, 20, 101 etc.are permitted, though.
Input
Input containsno more than 100 lines. Each line contains one integer N (1 ≤ N ≤ 2000).
Output
For each N,output the number of different (non-negative) numbers representable if you haveN matches.
Sample Input
3 4
Sample Output
2 4
题意
用n根火柴能组成多少个非负整数?火柴不必用完,组成的整数不能有前导0,但可以组成一个单独的整数0。
思路
把“已经使用过的火柴数i”当作一种状态进行递推,dp[i]表示用i根火柴能表示的数字的个数 dp[i] =sum(dp[i-c[j]]) (0 <= j <= 9)。注意dp[0]=1这个特殊的值是为了进行递推的,答案中没有这种一根火柴都不用情况,当然还有两点要注意。一是注意不能有前导0出现,即i==0时不能用6根火柴转移到i==6的状态。二是这里的递推没有包括单独用6根火柴组成一个数字0的情况,所以当火柴数n>=6时,答案还要加一。
数组s[]用来求前n项和,数字范围会很大用java写很方便。
代码
import java.util.*;
import java.math.*;
public class Main {
public static void main(String[] args) {
final int maxn = 2050;
final int c[] = { 6, 2, 5, 5, 4, 5, 6, 3, 7, 6 };
BigInteger dp[] = new BigInteger[maxn + 50];
BigInteger s[] = new BigInteger[maxn + 50];
dp[0] = BigInteger.ONE;
for (int i = 1; i < dp.length; i++) {
dp[i] = BigInteger.ZERO;
}
for (int i = 0; i < s.length; i++) {
s[i] = BigInteger.ZERO;
}
for (int i = 0; i <= maxn; i++) {
for (int j = 0; j < 10; j++) {
if (i != 0 || j != 0) {//不能有前导0
dp[i + c[j]] = dp[i + c[j]].add(dp[i]);
}
}
}
for (int i = 1; i <= maxn; i++) {
s[i] = s[i - 1].add(dp[i]);
}
Scanner input = new Scanner(System.in);
while (input.hasNext()) {
int n = input.nextInt();
if (n < 6) System.out.println(s[n]);
else System.out.println(s[n].add(BigInteger.ONE));//+1是指凑成一个单独的整数0,当然必须要至少6根火柴才可以
}
}
}