hdu1588:Gauss Fibonacci

对每个0<=i<n求f(g(i))的和,其中f(x)为斐波那契数列第x项,g(i)=k*i+b,k,b,n给定,模数给定。

斐波那契数有一种用矩阵乘法求的方法,这个矩阵A自己写,令F[i]为i和i+1的那个矩阵,F[i]=A^b*F[0],然后答案要求F[b]+F[k+b]+F[k*2+b]+……=(A^b+A^(k+b)+A^(2k+b)+……)*F[0]=(E+A^k+……+A^k^(n-1))*A^b*F[0]的[2,1]项。上面括号里就令B=A^k求E+B+B^2+……+B^(n-1),可以求吧!

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<math.h>
 5 //#include<iostream>
 6 using namespace std;
 7 
 8 #define LL long long
 9 LL K,b,n,mod;
10 typedef LL mat[5][5];
11 mat ans,base,E,a,f,t;
12 void copy(mat &a,mat b)
13 {
14     for (int i=1;i<=2;i++)
15         for (int j=1;j<=2;j++)
16             a[i][j]=b[i][j];
17 }
18 void mul(mat a,mat b,mat &ans)
19 {
20     mat t;
21     memset(t,0,sizeof(t));
22     for (int i=1;i<=2;i++)
23         for (int j=1;j<=2;j++)
24             for (int k=1;k<=2;k++)
25                 t[i][j]=(t[i][j]+a[i][k]*b[k][j]%mod)%mod;
26     copy(ans,t);
27 }
28 void add(mat a,mat b,mat &ans)
29 {
30     for (int i=1;i<=2;i++)
31         for (int j=1;j<=2;j++)
32             ans[i][j]=a[i][j]+b[i][j];
33 }
34 void init(mat &a)
35 {
36     a[1][1]=a[2][2]=1;
37     a[1][2]=a[2][1]=0;
38 }
39 void pow(mat a,LL b,mat &ans)
40 {
41     mat t,tmp;init(t);copy(tmp,a);
42     while (b)
43     {
44         if (b&1) mul(t,tmp,t);
45         mul(tmp,tmp,tmp);
46         b>>=1;
47     }
48     copy(ans,t);
49 }
50 void sum(mat a,LL b,mat &ans)
51 {
52     mat last,tmp,f,t;
53     memset(ans,0,sizeof(ans));
54     init(f);init(last);
55     copy(tmp,a);
56     while (b)
57     {
58         if (b&1)
59         {
60             mul(f,last,t);
61             add(ans,t,ans);
62             mul(last,tmp,last);
63         }
64         add(tmp,E,t);
65         mul(f,t,f);
66         mul(tmp,tmp,tmp);
67         b>>=1;
68     }
69 }
70 int main()
71 {
72     a[1][1]=a[1][2]=a[2][1]=1;a[2][2]=0;
73     E[1][1]=E[2][2]=1;E[1][2]=E[2][1]=0;
74     while (~scanf("%lld%lld%lld%lld",&K,&b,&n,&mod))
75     {
76         ans[1][1]=1;ans[1][2]=ans[2][1]=ans[2][2]=0;
77         pow(a,b,t);mul(t,ans,ans);
78         pow(a,K,base);sum(base,n,f);
79         mul(f,ans,ans);
80         printf("%lld\n",ans[2][1]);
81     }
82     return 0;
83 }
View Code

 

转载于:https://www.cnblogs.com/Blue233333/p/7460504.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值