码迷,mamicode.com
首页 > 其他好文 > 详细

CodeAction_beta02 斐波那契

时间:2019-01-26 11:18:33      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:斐波那契   str   分析   amp   注意   namespace   dea   long   define   

用第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 斐波那契

标签:斐波那契   str   分析   amp   注意   namespace   dea   long   define   

原文地址:https://www.cnblogs.com/PPXppx/p/10322496.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!