bnu dp

gabrielus

 

Description

gabrielus是个斐波那契数迷。他是如此的酷爱这个数列,因此他想知道很多关于这个数列的东西,比方说第N个斐波那契数是多少啊、前N项的和是多少 啊如何用若干个斐波那契数的和表示一个自然数啊之类之类的。今天他希望知道的是:他想用第1个、第2个…第N个斐波那契数构成一个长度为P的序列,每个斐 波那契数可以使用任意多次,但至少要使用一次,并且序列中任意两个相同的斐波那契数之间至少要隔着M个数,gabrielus希望知道满足条件的序列组成 方法有多少种。

记fib[i]表示第i个斐波那契数,fib[0]=fib[1]=1, fib[i]=fib[i-1]+fib[i-2] (i>1)。

Input

输入只有三个数N,M,P(1<=N<=P<=1000,0<=M<=N)。

Output

输出一个数字表示序列组成方法,由于结果可能很大,只需输出结果模上1000000007就可以。

Sample Input

2 1 4

Sample Output

2

这个状态表示很好,dp[i][j]代表长度为i个序列有j个不同的数组成,不好的是题目描述不是很清

#include <stdio.h>
#include <string.h>

long long mod = 1000000007;
long long dp[1010][1010];

void pd(int N, int M, int P)
{
long long re;
int i, j;
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for (i = 0; i <= P; i++)
{
for (j = 0; j <= N; j++)
{
dp[i + 1][j + 1] = dp[i][j] % mod ;// 插入一个新数,是没有考虑到是组合区别于dp[i+1][j+1]=dp[i][j]*(N-j)
if (j > M) dp[i + 1][j] = (dp[i + 1][j] + dp[i][j] * (j - M)) % mod;
}
}
re = dp[P][N];
for (i = 1; i <= N; i++){
re = (re * i) % mod;
}
printf("%lld\n", re);
}
char str[10];
int main()
{
int i, n, m, p;
while(scanf("%d%d%d", &n, &m, &p)==3)
{
pd(n, m, p);
}
return 0;
}





posted on 2012-04-02 11:28  Goal  阅读(287)  评论(0编辑  收藏  举报

导航