题目:
ChenJr已经两个月没有出门了,因此他已经无聊到开始用积木来玩搭房子游戏了。
ChenJr首先规定,对于搭建的每一栋房子,他只能选取长度为n的积木作为地基,之后他根据下述的规则进行搭建。
如果当前搭建的房子的最顶端的积木块的长度为k,那么ChenJr可以选择一个正整数i,(i∈[1,k2]),并在房子顶端放置一个长度为i的积木。或者ChenJr可以选择不再继续放置积木,代表当前的房子已经搭建好了。
ChenJr不喜欢搭建款式相同的房子,而两个房子的款式相同,当且仅当两个房子使用的种类和数量都相同。现在你可以认为ChenJr有无穷个大小在[1,n]的积木,现在你需要告诉ChenJr,ChenJr最多可以搭建多少个不同款式的房子。最后的结果可能会很大,你需要将结果mod 109+7。
Input
一行输入一个正整数n (1≤n≤106),代表ChenJr只能选取长度为n的积木作为地基。
Output
一行输出ChenJr最多可以搭建多少个不同款式的房子。你需要将你得出的答案mod 109+7。
Examples
inputCopy
1
outputCopy
1
inputCopy
4
outputCopy
4
Note
对于样例2,可以构建3种不同的房子:
房子1:4
房子2: 4 2
房子3: 4 1
房子4: 4 2 1
(数字从左到右依次为地基到顶端的积木长度)
这个题意就是给出一个n,然后让你以n为基底,每次往上面放的限制都是上一层的n/2以下,问多少种不同的放法;
然后就知道n基底,然后上面的数就是n/2…1和不放;如果是n/2,怎么在n/2上面放呢,那么问题已经呼之欲出,这就是一个dp,dp[i]表示i为基底的放法:dp[i]=dp[i/2]+…+dp[1]+1 (除了i自己上面什么都不放);
但是我们会发现一个问题,dp[i/2]+…+dp[1]太多了,总不能for把,所以我们用一个前缀和all[i]=dp[i]+…+dp[1]。
核心代码:
dp[1]=1;
all[1]=1;
for(int time=2;time<1000001;time++)
{
dp[time]=all[time/2]+1;
dp[time]%=mod;
all[time]=all[time-1]+dp[time];
all[time]%=mod;
}
printf("%d\n",dp[n]);