题意:
给出自然数 n n n,要求按如下方式构造数列:
- 只有一个数字 n n n 的数列是一个合法的数列。
- 在一个合法的数列的末尾加入一个自然数,但是这个自然数不能超过该数列最后一项的一半,可以得到一个新的合法数列。
请你求出,一共有多少个合法的数列。两个合法数列 a , b a, b a,b 不同当且仅当两数列长度不同或存在一个正整数 i ≤ ∣ a ∣ i \leq |a| i≤∣a∣,使得 a i ≠ b i a_i \neq b_i ai=bi。
题解:
在搜索不确定时间复杂度的情况下,尽量避开。
从前往后也可以,我这里用的是从后往前的,也就是从小的数开始每次加变大的。我们知道每次至少*2,所以最多也就增大10次。那么dp[i][j]表示到了第i个数,值为j的情况数。它可以从dp[i-1][1:j/2]转移过来。我们从小往大枚举j的话,就可以用一个sum维护i-1位置上,值≤j/2的所有情况和。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e3+5;
ll dp[15][N];
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n/2;i++)dp[1][i]=1;
ll ans=1;
for(int i=2;i<=10;i++){
ll sum=0,pos=1;
for(int j=1<<i-1;j<=n/2;j++){
while(pos*2<=j)sum+=dp[i-1][pos++];
dp[i][j]=sum;
}
while(pos*2<=n)sum+=dp[i-1][pos++];
ans+=sum;
}
printf("%lld\n",ans);
return 0;
}