蒜头君的兔子
蒜头君的兔子
2017-09-03
题目描述
蒜头君的小伙伴在 第一年 送给他一对 一岁 的兔子,并告诉他:这种兔子 刚生下来时算 0 岁,到了 2 岁时就可以繁殖了,它在 2−10 岁时,每年会生下来一对兔子,这些兔子到了 2 岁也可以繁殖,但这些兔子在 10 岁那年生完仔后 不久就会死亡,蒜头君想知道,第 n 年兔子 产仔之后(第 n 年 10 岁的兔子此时已经死亡),他会有多少对兔子。结果对 1000000007 取模。
输入格式
共一行,一个正整数 n,表示蒜头君想知道第 n 年的兔子总对数。
输出格式
输出一个整数,表示第 n 年兔子总对数对1000000007 取模的值。
数据规模
对于 30% 的数据,满足1<=n<=10^3;
对于 60% 的数据,满足 1 ≤n≤10^5;
对于 100% 的数据,满足 1≤n≤10^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; }
s:烤lilo的w,本lilo不怕你
w:翻个面~撒点盐~♪