Yet Another Number Sequence

题意:

$F_0 = 0, F_1 = 1, F_n = F_{n-1} + F_{n-2}$

求解$\sum_{i=1}^n{ F_i i^K } \  mod \  10^9+7$。

 

解法:

记$S(n,m) = \sum_{i=1}^n { F_i i^m}$

这样有:

$$S(2n,m)  = \sum_{i=1}^n{F_i i^m} + \sum_{i=1}^n{F_{i+n} (i+n)^m}$$

记$G = \lgroup \begin{matrix} 1 & 1 \\ 1 & 0 \end{matrix} \rgroup$

有$F_n = G_{1,1}$

将$S(n,m)$的含义换为对应求和的矩阵。

1.考虑从$S(n,m)$推到$S(2n,m)$

$$S(2n,m) = \sum_{i=1}^n{G^n i^m} + G^n \sum_{i=1}^n{G^{i} (i+n)^m}$$

$$S(2n,m) = \sum_{i=1}^n{G^n i^m} + G^n \sum_{i=1}^n{G^{i} \sum_{r=0}^m{i^rm^{m-r}C_m^r}}$$

$$S(2n,m) = \sum_{i=1}^n{G^n i^m} + G^n \sum_{r=0}^m{m^{m-r}C_m^r S(n,r)}$$

这样$O(K)$完成单次转移。 

2.考虑从$S(n,m)$推到$S(n+1,m)$

$$S(n+1,m) = S(n,m) + (n+1)^m G^{n+1}$$

这样分治下去,总效率$O(K^2 logn)$

(注意本题中n过大,要先对于n取模再进行乘法)

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 
  5 #define LL long long
  6 #define P 1000000007LL
  7 
  8 using namespace std;
  9     
 10 struct MA
 11 {
 12     LL a[2][2];
 13     
 14     void init()
 15     {
 16         memset(a,0,sizeof(a));
 17     }
 18     
 19     MA operator*(const MA &x)const
 20     {
 21         MA c;
 22         for(int i=0,j,k;i<2;i++)
 23             for(j=0;j<2;j++)
 24             {
 25                 c.a[i][j]=0;
 26                 for(k=0;k<2;k++)
 27                 {
 28                     c.a[i][j]+=a[i][k]*x.a[k][j]%P;
 29                     if(c.a[i][j]>=P) c.a[i][j]-=P;
 30                 }
 31             }
 32         return c;
 33     }
 34     
 35     MA operator*(const LL &x)const
 36     {
 37         MA c;
 38         for(int i=0,j;i<2;i++)
 39             for(j=0;j<2;j++)
 40                 c.a[i][j] = a[i][j]*x%P;
 41         return c;
 42     }
 43     
 44     MA operator+(const MA &x)const
 45     {
 46         MA c;
 47         for(int i=0,j;i<2;i++)
 48             for(j=0;j<2;j++)
 49                 c.a[i][j] = (a[i][j]+x.a[i][j])%P;
 50         return c;
 51     }
 52     
 53     void print()
 54     {
 55         puts("Matrix");
 56         for(int i=0,j;i<2;i++)
 57         {
 58             for(j=0;j<2;j++) cout<<a[i][j]<<' ';
 59             cout<<endl;
 60         }
 61     }
 62 };
 63 
 64 MA G,Gn;
 65 MA S[2][50];
 66 LL n,power[50],C[50][50];
 67 int K,now;
 68 
 69 void solve(LL n)
 70 {
 71     if(n==1)
 72     {
 73         now=0;
 74         Gn = G;
 75         for(int i=0;i<=K;i++) S[now][i] = G;
 76         return;
 77     }
 78     solve(n>>1);
 79     now^=1;
 80     MA tmp;
 81     power[0]=1;
 82     for(int k=1;k<=K;k++) power[k] = power[k-1]*((n>>1LL)%P)%P;
 83     for(int k=0;k<=K;k++)
 84     {
 85         tmp.init();
 86         for(int r=0;r<=k;r++)
 87             tmp = tmp + ( S[now^1][r] * (C[k][r]*power[k-r]%P) );
 88         S[now][k] = S[now^1][k] + (Gn * tmp);
 89     }
 90     Gn = Gn*Gn;
 91     if(n&1)
 92     {
 93         Gn = Gn*G;
 94         power[0]=1LL;
 95         for(int k=0;k<=K;k++)
 96         {
 97             S[now][k] = S[now][k] + (Gn * power[k]);
 98             power[k+1] = power[k]*(n%P)%P;
 99         }
100     }
101 }
102 
103 int main()
104 {
105     G.a[0][0]=1; G.a[0][1]=1;
106     G.a[1][0]=1; G.a[1][1]=0;
107     while(~scanf("%I64d%d",&n,&K))
108     {
109         C[0][0]=1;
110         for(int i=1;i<=K;i++)
111         {
112             C[i][0]=1;
113             for(int j=1;j<=i;j++)
114             {
115                 C[i][j] = C[i-1][j-1]+C[i-1][j];
116                 if(C[i][j]>=P) C[i][j] -= P;
117             }
118         }
119         solve(n);
120         cout << S[now][K].a[0][0] << endl;
121     }
122     return 0;
123 }
View Code

 

转载于:https://www.cnblogs.com/lawyer/p/6605980.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值