zoukankan      html  css  js  c++  java
  • 2017辽宁冬令营-3.斐波那契

    斐波那契(fib.pas/c/cpp)
    题目大意
    众所周知,斐波那契数列就是 F(n)=F(n-1)+F(n-2),F(1)=F(2)=1,然后大小为 n 的一维
    斐波那契表就是 F(1),F(2),F(3),F(4)…F(n)。我们定义二维的斐波那契表的第(i,j)个位置也就是
    a(i,j)=F(i+j-1),大小为 n 的二维斐波那契表如下表:
    F(1) F(2) F(3) … F(n)
    F(2) F(3) F(4) … F(n+1)
    F(3) F(4) F(5) … F(n+2)
    … … … … …
    F(n) F(n+2) F(n+3) … F(2n-1)
    我们定义k维大小为n的斐波那契表的第(i 1 ,i 2 ,…,i k )项a(i 1 ,i 2 ,…,i k )=F(i 1 +i 2 +…+i k -k+1)。 其中,
    i 1 ,i 2 ,…,i k 均为不超过 n 的正整数。你的任务是,给你 n 和 k 要求求出 k 维大小为 n 的斐波那
    契表所有元素之和 mod 1,000,000,007 的值。
    输入文件
    输入文件为 fib.in。
    一行两个数 n 和 k。
    输出文件
    输出文件为 fib.out。
    一行一个数表示答案
    样例输入 1
    2 2
    样例输出 1
    5
    样例输入 2
    4 1
    样例输出 2
    7
    样例输入 3
    1 3
    样例输出 3
    1
    数据规模与约定
    对于 20%的数据,n,k ≤10 5 ;
    另有 20%的数据,k=1;
    对于 60%的数据,k≤10^5
    对于 100%的数据,n,k≤10^9+7

    ——————————————————————————题解

    这是一个需要推两个矩阵的题

    一个矩阵是在第k维里层和层之间的转移,一个矩阵是第k维到第k+1维

    F[i][j]表示第i维第j层的和

    S[i][j]表示第i维前j层的和

    举个栗子n=4

    1维时 1 1 2 3

    n+1  1 1 2 3 5

    2维的第一层 

    1 1 2 3

    第二层

    [1 2 3 4]+[1 1 2 3 5]-[1]

    1 2 3 5

    第二层的一二层

    1 1 2 3

    1 2 3 5

    然后写矩阵

    答案是(A^(n-1)*B)^k

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>//important
     4 #include <algorithm>
     5 #define siji(i,x,y) for(int i=(x);i<=(y);++i)
     6 #define gongzi(j,x,y) for(int j=(x);j>=(y);--j)
     7 #define xiaosiji(i,x,y) for(int i=(x);i<(y);++i)
     8 #define sigongzi(j,x,y) for(int j=(x);j>(y);--j)
     9 #define ivorysi
    10 #define inf 0x7f7f7f7f 
    11 #define mod 1000000007
    12 typedef long long ll;
    13 using namespace std;
    14 struct node {
    15     ll m[5][5];
    16     node() {memset(m,0,sizeof(m));}
    17     node operator * (const node &rhs) const{
    18         node tmp;
    19         siji(i,1,4) {
    20             siji(j,1,4) {
    21                 siji(k,1,4) {
    22                     tmp.m[j][i]=(m[k][i]*rhs.m[j][k]+tmp.m[j][i])%mod;
    23                 }
    24                 
    25             }
    26         }
    27         return tmp; 
    28     }
    29 };
    30 node pow(node c,int o) {
    31     if(o==1) return c;
    32     node t=pow(c,o>>1);
    33     if(o&1) {
    34         return t*t*c;
    35     }
    36     else {
    37         return t*t;
    38     }
    39 }
    40 int n,k;
    41 void solve() {
    42     scanf("%d%d",&n,&k);
    43     if(n==1) {puts("1");return;}
    44     node a,b,x;
    45     ll u[5][5]={ {0,0,0,0,0},{0,1,0,0,0},{0,0,0,1,0},{0,0,1,1,0},{0,0,0,1,1} };
    46     memcpy(a.m,u,sizeof(u));
    47     ll z[5][5]={ {0,0,0,0,0},{0,0,0,0,1},{0,0,0,0,1},{0,-1,0,1,1},{0,0,0,0,1} };
    48     memcpy(b.m,z,sizeof(z));
    49     x=a;
    50     x=pow(x,n-1);
    51     x=x*b;
    52     x=pow(x,k);
    53 
    54     printf("%d
    ",(ll)(x.m[4][1]+x.m[4][2]+x.m[4][3]+x.m[4][4])%mod);
    55 }
    56 int main(int argc, char const *argv[])
    57 {
    58 #ifdef ivorysi
    59     freopen("fib.in","r",stdin);
    60     freopen("fib.out","w",stdout);
    61 #else
    62     freopen("f1.in","r",stdin);
    63 #endif
    64     solve();
    65     return 0;
    66 }
  • 相关阅读:
    C++中逻辑操作符的重载分析
    不要62
    P1052 过河
    P1029 最大公约数和最小公倍数问题
    P1345 [USACO5.4]奶牛的电信Telecowmunication
    Dining
    Dinic
    [Scoi2015]小凸玩矩阵
    12.16
    bzoj 3529
  • 原文地址:https://www.cnblogs.com/ivorysi/p/6395691.html
Copyright © 2011-2022 走看看