zoj3690(递推)

来源:互联网 发布:程序员的自我修养 下载 编辑:程序博客网 时间:2024/05/09 22:31

题意:有n个人,1到m个数,这n个人,每人选一个数字,要求相邻的两个人选择的数不能相等,相等时不能小于k

a[i] 表示第i位置的>k的种数 。

b[i]表示第i位置<=k的种数。

a[1]=m-k; b[1]=k;

用矩阵求解;

#include<stdio.h>const long long mod=1000000007;long long a[4],b[4];long long m,k;void fun(long long t){    b[0]=( (a[0]*a[0])%mod+(a[1]*a[2])%mod )%mod;    b[1]=( (a[0]*a[1])%mod+(a[1]*a[3])%mod )%mod;    b[2]=( (a[2]*a[0])%mod+(a[3]*a[2])%mod )%mod;    b[3]=( (a[2]*a[1])%mod+(a[3]*a[3])%mod )%mod;    a[0]=b[0]; a[1]=b[1];    a[2]=b[2]; a[3]=b[3];    if(t)    {        b[0]=( a[0]*(m-k)%mod + a[1]*(m-k)%mod)%mod;        b[1]=(a[0]*k%mod+a[1]*(k-1)%mod)%mod;        b[2]=(a[2]*(m-k)%mod+a[3]*(m-k)%mod)%mod;        b[3]=(a[2]*k%mod+a[3]*(k-1)%mod)%mod;        a[0]=b[0]; a[1]=b[1];        a[2]=b[2]; a[3]=b[3];    }}void fib(long long n){    if(n == 1) return;    fib(n/2);    if(n%2==1) fun(1);    else fun(0);}int main(){    long long n;    while(scanf("%lld%lld%lld",&n,&m,&k)!=EOF)    {        a[0]=m-k;a[1]=k;        a[2]=m-k; a[3]=k-1;        fib(n);        printf("%lld\n",(a[0]%mod+a[1]%mod)%mod);    }    return 0;}


原创粉丝点击