zoukankan      html  css  js  c++  java
  • 蒜头君的兔子

    蒜头君的兔子

    2017-09-03


    题目描述

    蒜头君的小伙伴在 第一年 送给他一对 一岁 的兔子,并告诉他:这种兔子 刚生下来时算 0 岁,到了 2 岁时就可以繁殖了,它在 210 岁时,每年会生下来一对兔子,这些兔子到了 2 岁也可以繁殖,但这些兔子在 10 岁那年生完仔后 不久就会死亡,蒜头君想知道,第 n 年兔子 产仔之后(第 n 年 10 岁的兔子此时已经死亡),他会有多少对兔子。结果对 1000000007 取模。


    输入格式

    共一行,一个正整数 n,表示蒜头君想知道第 n 年的兔子总对数。


    输出格式

    输出一个整数,表示第 n 年兔子总对数对1000000007 取模的值。


    数据规模

    对于 30% 的数据,满足1<=n<=10^3​​;

    对于 60% 的数据,满足 1 n10^5​​;

    对于 100% 的数据,满足 1n10​^9​​。


    样例输入1
    10
    样例输出1
    88

    样例输入2

    88

    样例输出2

    352138150

    样例输入3

    10086

    样例输出3

    405567313

    一看到这个题就是一个关于斐波那契数列的题,就是加了一点变形.
    前9项没有死兔子的时候就是斐波那契.到了第十项,发现减了一只,(死掉了10岁的),但是代替他的是一只0岁的小兔.
    所以10岁以上的兔子对数列没有贡献.于是就可以f[i]=f[i-1]+f[i-2]-f[i-10](i>=10)
    但这样只能过60%的点.所以要用矩阵优化.
    我的矩阵是用重载运算符做的.......x
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #define ll long long  
    using namespace std;
    const ll mod=1000000007;
    int read(){
        int an=0,f=1;
        char ch=getchar();
        while(!('0'<=ch&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=an*10+(ch-'0');ch=getchar();}
        return an*f;
    }
    int n;
    ll ans;
    struct saber{
    ll a[15][15];
    }a,d;
    saber operator *(saber A,saber B){
        saber s;
        for(int i=0;i<=10;i++)
        for(int j=0;j<=10;j++)s.a[i][j]=0;
        for(int i=0;i<=10;i++)
            for(int j=0;j<=10;j++)
                for(int k=0;k<=10;k++)
                    s.a[i][j]=(s.a[i][j]+A.a[i][k]*B.a[k][j])%mod;
        return s;
    }
    saber qk(int n)
    {
        saber s;
        for(int i=0;i<=10;i++)
        for(int j=0;j<=10;j++)s.a[i][j]=0;
        for(int i=0;i<=9;i++)s.a[i][i]=1;
        while(n){
            if(n&1)s=s*a;
            a=a*a;
            n>>=1;
        }
        return s;
    }
    int main(){
        n=read();
        for(int i=1;i<=10;i++){
        a.a[i][i-1]=1;a.a[0][i]=1;
        }
        a.a[0][10]=0;
        d=qk(n);
        for(int i=0;i<=9;i++)
        ans=(ans+d.a[i][0])%mod;
        cout<<ans;
        return 0;
    }
    兔子

    by:s_a_b_e_r



     蒜头君家到底有多大,能养下这么多兔子x
     依然是递推+矩阵优化……
     递推方程超级好推……就是一个斐波那契数列
     然而这个矩阵并不好推qwq
     表示是看着这个博客推的矩阵
     愉快地重载*,然后矩阵快速幂
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define ll long long
    const ll mod=1000000007;
    using namespace std;
    struct matrix{
    ll a[15][15];
    }m,ans,a;
    matrix operator * (matrix x,matrix y)
    {
           matrix s;
           memset(s.a,0,sizeof(s.a));
           for(int i=0;i<=10;++i)
           for(int j=0;j<=10;++j)
           for(int l=0;l<=10;++l)
           s.a[i][j]=(s.a[i][j]+x.a[i][l]*y.a[l][j])%mod;
           return s;
    } 
    matrix kp(ll q)
    {
           matrix s;
           memset(s.a,0,sizeof(s));
           for(int i=0;i<=10;++i)s.a[i][i]=1;
           while(q)
           {
             if(q&1)s=s*m;
             m=m*m;
             q>>=1;
           }
           return s;
    }
    int n;
    int main()
    {
        cin>>n;
        for(int i=0;i<=10;++i)
        {
          if(i&&i!=10)m.a[i][0]=1;
          if(i<=9)m.a[i][i+1]=1;
        }
        for(int i=0;i<=9;++i)a.a[i][i]=1;
        matrix ans=kp(n);
        ll sum=0;
        for(int i=0;i<=9;i++)sum=(sum+ans.a[0][i])%mod;
        cout<<sum<<endl;
        return 0;
    }
    rabbits
     by:wypx

    s:烤lilo的w,本lilo不怕你
    w:翻个面~撒点盐~♪
  • 相关阅读:
    android 解密工具
    android打包需要的图标
    Mac 创建软链接
    历届试题 Excel地址
    算法训练 字串统计
    最长回文子串
    算法提高 P1001【大数乘法】
    算法提高 拿糖果【埃氏筛 动态规划】
    算法训练 未名湖边的烦恼
    算法提高 合并石子【动态规划】
  • 原文地址:https://www.cnblogs.com/ck666/p/7470756.html
Copyright © 2011-2022 走看看