问题描述
我们把一个数称为有趣的,当且仅当:
因此,符合我们定义的最小的有趣的数是2013。除此以外,4位的有趣的数还有两个:2031和2301。
请计算恰好有n位的有趣的数的个数。由于答案可能非常大,只需要输出答案除以1000000007的余数。
输入格式
输入只有一行,包括恰好一个正整数n (4 ≤ n ≤ 1000)。
输出格式
输出只有一行,包括恰好n 位的整数中有趣的数的个数除以1000000007的余数。
样例输入
4
样例输出
3
首先定义f[i]表示为i位数满足条件的组合数。
f[i,2]表示头为2的后面i位共有满足条件的组合数。
根据图可以看出20(是指第一位为2第二位为0,当然倒过来也是成立的)后面可能的组合和200后面可以选择的组合是相同的,这点必须要先明白。这样就有如下等式成立:
f[i, 200] = f[i, 20]
f[i, 220] = f[i, 20]
下面开始进行迭代公式:
因为第一个数字必须为2否则会违反规则,所以有如下公式:
f[i] = f[i-1, 2]/意思为i位数的满足规则的组合数与2为头剩下的i-1位满足规则的组合数相等。
另外,f[i]即为我们所求的在i位数下的组合数。
第一位为2,第2位上只能是0、2、3之中的一个,所以可以有如下公式:
f[i-1, 2] = f[i-2, 20] + f[i-2, 22] + f[i-2, 23]
根据前面公式,有f[i-2, 22] = f[i-2, 2]
同理有如下公式:
f[i-2, 20] = f[i-3, 200] + f[i-3, 201] + f[i-3, 202] + f[i-3, 203] = f[i-3, 20] + f[i-3, 201] + f[i-3, 20] + f[i-3, 203]
f[i-2, 22](=f[i-2, 2]) = f[i-3, 220] + f[i-3, 222] + f[i-3, 223] = f[i-3, 20] + f[i-3, 2] + f[i-3, 23]
f[i-2, 23] = f[i-3, 230] + f[i-3, 233] = f[i-3, 230] + f[i-3, 23]
f[i-3, 230] = f[i-4, 2300] + f[i-4, 2301] + f[i-4, 2303] = f[i-4, 230] + f[i-4, 2301] + f[i-4, 230]
f[i-3, 201] = f[i-4, 2011] + f[i-4, 2012] + f[i-4, 2013] = f[i-4, 201] + f[i-4, 201] + f[i-4, 2013]
公式里面的{2}、{20}、{23}、{201}、{203}、{2031}称为数码。
另外因为2013后面的数字只能为1或者3,组合数为2,即
f[1, 2013] = 2;可以推导出f[i, 2013] = 2^(i);
下面就是数列的计算,高中已经学过了,计算的结果为
f[i] = f[i-1, 2] = (i-1)(i-4)2^(i-3)+i-1
从而得到的结果为N依次为4到15,结果为
Columns 1 through 7
3 20 85 294 903 2568 6921
Columns 8 through 12
17930 45067 110604 266253 630798
用笔算大概就是这个思路。
通过程序实现,就是针对上面的迭代公式进行迭代。
java程序代码如下:
package test;
import java.util.Arrays;
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
int N = 15;
long[] count = new long[8];
count[6] = 0;
count[7] = 1;
long mod = 1000000007;
for (int i = 2; i <= N; ++i) {
long[] newCount = new long[8];
newCount[0] = (count[0] * 2 + count[1] + count[3]) % mod;
newCount[1] = (count[1] * 2 + count[2] + count[5]) % mod;
newCount[2] = (count[2] + count[6]) % mod;
newCount[3] = (count[3] * 2 + count[4] + count[5]) % mod;
newCount[4] = (count[4] + count[7]) % mod;
newCount[5] = (count[5] * 2 + count[6] + count[7]) % mod;
newCount[6] = 0;
newCount[7] = 1;
count = newCount;
System.out.println(count[0]);
}
}
}