CodeAction_beta02 斐波那契

Posted ppxppx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeAction_beta02 斐波那契相关的知识,希望对你有一定的参考价值。

用第1个,第2个...第N个斐波那契数构成一个长度为P的序列,每个斐波那契数可以使用任意多次,但至少要使用一次,并且序列中任意两个相同的斐波那契数之间至少要隔着 M 个数, 求满足条件的序列组成方法有多少种?输出答案对1e9+7取模.

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

分析:本来标题是想叫做"与fib完全无关的一道fib题".不过个人认为这的确是道思维好题.

因为题目说了所有数都要出现至少一次 所以只需考虑其组合而不用考虑其排列 最后乘个n!就是答案.(意思就是可以当做这 N 个数是无序的)所以说本题与fib无关,你就当做题目给你了n个数就行了.

(f[i][j])表示序列前i个放了j种数的方案数.考虑放第i+1个时的状态转移.

不难想到,此时我们有两种选择.

(1)放一个新的数,则状态转移为(f[i+1][j+1])

(2)放一个之前已经出现过的数,则状态转移为(f[i+1][j])

对于第一种情况,有(f[i+1][j+1]+=f[i][j]);

对于第二种情况,因为"序列中任意两个相同的斐波那契数之间至少要隔着M个数",所以序列末尾的M种数是不可以放的,则有(f[i+1][j]+=f[i][j]*(j-m))

注意一边算一边取模,然后"十年oi一场空,不开long long..."

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)w=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){s=s*10+ch-‘0‘;ch=getchar();}
    return s*w;
}
const int mod=1e9+7;
int n,m,p;
ll ans,f[2005][2005];
int main(){
    n=read();m=read();p=read();
    f[0][0]=1;
    for(int i=0;i<=p;i++)
    for(int j=0;j<=n;j++){
        f[i+1][j+1]+=f[i][j]%mod;
        if(j>m)f[i+1][j]=(f[i+1][j]+f[i][j]*(j-m))%mod;
    }
    ans=f[p][n]%mod;
    for(int i=1;i<=n;i++)
    ans=(ans*i)%mod;
    cout<<ans<<endl;
    return 0;
}

以上是关于CodeAction_beta02 斐波那契的主要内容,如果未能解决你的问题,请参考以下文章

什么是斐波那契数列?在日常生活中有什么实例?

斐波那契数列在生活中都有哪些典型的应用

08《算法入门教程》递归算法之斐波那契数列

斐波那契数列

谁能帮我用JAVA编写一个斐波那契数列,用eclipse实现,代码不对不采纳!

编写一递归函数求斐波那契数列的前40项