第九题 序列计数
题目
【问题描述】
小明想知道,满足以下条件的正整数序列的数量:
1. 第一项为 n;
2. 第二项不超过 n;
3. 从第三项开始,每一项小于前两项的差的绝对值。
请计算,对于给定的 n,有多少种满足条件的序列。
【输入格式】
输入一行包含一个整数 n。
【输出格式】
输出一个整数,表示答案。答案可能很大,请输出答案除以10000的余数。
【样例输入】
4
【样例输出】
7
【样例说明】
以下是满足条件的序列:
4 1
4 1 1
4 1 2
4 2
4 2 1
4 3
4 4
【评测用例规模与约定】
对于 20% 的评测用例,1 <= n <= 5;
对于 50% 的评测用例,1 <= n <= 10;
对于 80% 的评测用例,1 <= n <= 100;
对于所有评测用例,1 <= n <= 1000。
思路:记忆化搜索。
#include<iostream>
#include<cstring>
#include<stack>
#include<ctime>
#define ll long long
using namespace std;
const int mod = 10000;
ll dp[1010][1010];
ll dfs(int x, int y)
{
if(dp[x][y]) return dp[x][y];
else
{
ll rul = 1;
for(int i=1; i<abs(x-y); i++)
{
rul = (rul + dfs(y,i)) % mod;
}
dp[x][y] = rul;
return rul;
}
}
int main()
{
clock_t start,end;
int n;
cin>>n;
start = clock();
ll ans = 0;
for(int i=1; i<=n; i++)
{
ans =(ans + dfs(n,i)) % mod;
}
end = clock();
printf("%lld\n",ans);
cout<<(end - start);
return 0;
}
但是这么写时间复杂度是O(N^3),只能过掉%80的样例。输入1000后,输出:
递归过程要用掉3043ms,超时。
将递归过程进行优化,dfs(x,y) = 1 + dfs(x,y-1) + dfs(y,abs(x-y)-1),这里的x,y是指,在前一项为x的情况下,(x,1),(x,2)....(x,y)每一项以及其延申项的情况数的和。1为其本身的一种情况(x,y), dfs(x,y-1)为(x,1),(x,2)....(x,y-1)每一项以及其延申项的情况数的和,dfs(y,abs(x-y)-1) 为(x,y)本身 的延申情况和。
#include<iostream>
#include<cstring>
#include<stack>
#include<ctime>
#define ll long long
using namespace std;
const int mod = 10000;
ll dp[1010][1010];
ll dfs(int x, int y)
{
if(y <= 0) return 0;
if(dp[x][y]) return dp[x][y];
else
{
dp[x][y] =(1 + dfs(x,y-1) + dfs(y,abs(x-y)-1)) % mod;
return dp[x][y];
}
}
int main()
{
clock_t start,end;
int n;
cin>>n;
start = clock();
ll ans = dfs(n,n);
end = clock();
printf("%lld\n",ans);
cout<<(end - start);
return 0;
}
输入1000
可见时间节约了很多,复杂度O(N^2).