fuzhou 1683 纪念SlingShot ***

Problem 1683 纪念SlingShot

Accept: 361    Submit: 1287
Time Limit: 1000 mSec    Memory Limit : 32768 KB

Problem Description

已知 F(n)=3 * F(n-1)+2 * F(n-2)+7 * F(n-3),n>=3,其中F(0)=1,F(1)=3,F(2)=5,对于给定的每个n,输出F(0)+ F(1)+ …… + F(n) mod 2009。

Input

第一行是一整数m,代表总共有m个cases。

Output

对于每个case,输出一行。格式见样例,冒号后有一个空格。

Sample Input

2 3 6

Sample Output

Case 1: 37 Case 2: 313

Source

FOJ月赛-2009年2月- Coral

 

 
题意不看,刚开始觉得好水。直接快速幂就可以做。
后来发现求和的,囧...
————————————————————————————
 
  1 /*
  2 矩阵构造:
  3 假设前N项和为S(n), 那么可以推出 S(n)=S(n-1)+f(n);
  4 得到一个矩阵:
  5 
  6 | 1 1 0 0 | | s(n-1) |   |  S(n)  |
  7 | 0 3 2 7 | |  f(n)  | = | f(n+1) |
  8 | 0 1 0 0 | | f(n-1) |   |  f(n)  |
  9 | 0 0 1 0 | | f(n-2) |   | f(n-1) |
 10 
 11 然后每一个N,一次快速幂,过了?额,下面就是这样的代码
 12 超时ing...
 13 
 14 那么就要优化了。优化:题目中矩阵是不变的,只是单纯的问
 15 n的值。保存2^i的结果。每一个数字都能由2^i组成。(二进制优化)
 16 
 17 这样就节省了很多的时间。
 18 484 ms
 19 
 20 特别注意:
 21 在最初的编写过程中,我只是用 (M_tom.mat[1][1]*4+M_tom.mat[1][2]*5)%mod;
 22 这样做的结果是答案偏小了。问题在于还要加上 (M_tom.mat[1][3]*3+M_tom.mat[1][4]*1);
 23 这就是数学的问题了.....囧
 24 动手试一试
 25 */
 26 
 27 /*
 28 #include<iostream>
 29 #include<cstdio>
 30 #include<cstring>
 31 #include<cstdlib>
 32 using namespace std;
 33 typedef __int64 LL;
 34 const __int64 mod=2009;
 35 
 36 struct Matrix
 37 {
 38     LL mat[6][6];
 39     void ini()
 40     {
 41         memset(mat,0,sizeof(mat));
 42     }
 43     void first_ini()
 44     {
 45         for(LL i=1;i<=4;i++)
 46         for(LL j=1;j<=4;j++)
 47         if(i==j) mat[i][j]=1;
 48         else mat[i][j]=0;
 49     }
 50 }M_hxl,M_tom;
 51 
 52 
 53 void make_first()
 54 {
 55     M_hxl.mat[1][1]=1;M_hxl.mat[1][2]=1;M_hxl.mat[1][3]=0;M_hxl.mat[1][4]=0;
 56     M_hxl.mat[2][1]=0;M_hxl.mat[2][2]=3;M_hxl.mat[2][3]=2;M_hxl.mat[2][4]=7;
 57     M_hxl.mat[3][1]=0;M_hxl.mat[3][2]=1;M_hxl.mat[3][3]=0;M_hxl.mat[3][4]=0;
 58     M_hxl.mat[4][1]=0;M_hxl.mat[4][2]=0;M_hxl.mat[4][3]=1;M_hxl.mat[4][4]=0;
 59 }
 60 
 61 Matrix Multiply(Matrix cur,Matrix now)
 62 {
 63     Matrix ww;
 64     ww.ini();
 65     for(LL i=1;i<=4;i++)
 66     for(LL k=1;k<=4;k++)
 67     if(cur.mat[i][k])
 68     {
 69         for(LL j=1;j<=4;j++)
 70         if(now.mat[k][j])
 71         {
 72             ww.mat[i][j]+=cur.mat[i][k]*now.mat[k][j];
 73             if(ww.mat[i][j]>=mod)
 74             ww.mat[i][j]%=mod;
 75         }
 76     }
 77     return ww;
 78 }
 79 
 80 void power_sum2(LL n)
 81 {
 82       M_tom.first_ini();
 83       while(n)
 84       {
 85           if(n&1)
 86           {
 87               M_tom=Multiply(M_hxl,M_tom);
 88           }
 89           n=n>>1;
 90           M_hxl=Multiply(M_hxl,M_hxl);
 91       }
 92       LL sum=0;
 93       sum=(sum+M_tom.mat[1][1]*4)%mod;
 94       sum=(sum+M_tom.mat[1][2]*5)%mod;
 95       sum=(sum+M_tom.mat[1][3]*3)%mod;//!!!开始时没有加
 96       sum=(sum+M_tom.mat[1][4]*1)%mod;//!!!开始时没有加
 97       printf("%I64d\n",sum);
 98 }
 99 
100 int main()
101 {
102     LL T,n,i;
103     while(scanf("%I64d",&T)>0)
104     {
105         for(i=1;i<=T;i++)
106         {
107             scanf("%I64d",&n);
108             printf("Case %I64d: ",i);
109             if(n==0)printf("1\n");
110             else if(n==1) printf("4\n");
111             else if(n==2) printf("9\n");
112             else
113             {
114                 make_first();
115                 power_sum2(n-1);
116             }
117         }
118     }
119     return 0;
120 }
121 
122 
123 */
124 
125 #include<iostream>
126 #include<cstdio>
127 #include<cstring>
128 #include<cstdlib>
129 using namespace std;
130 typedef __int64 LL;
131 const __int64 mod=2009;
132 
133 struct Matrix
134 {
135     LL mat[6][6];
136     void ini()
137     {
138         memset(mat,0,sizeof(mat));
139     }
140     void first_ini()
141     {
142         for(LL i=1;i<=4;i++)
143         for(LL j=1;j<=4;j++)
144         if(i==j) mat[i][j]=1;
145         else mat[i][j]=0;
146     }
147     void init()
148     {
149         mat[1][1]=1;mat[1][2]=1;mat[1][3]=0;mat[1][4]=0;
150         mat[2][1]=0;mat[2][2]=3;mat[2][3]=2;mat[2][4]=7;
151         mat[3][1]=0;mat[3][2]=1;mat[3][3]=0;mat[3][4]=0;
152         mat[4][1]=0;mat[4][2]=0;mat[4][3]=1;mat[4][4]=0;
153     }
154 }M_hxl[40],M_tom;
155 
156 Matrix Multiply(Matrix cur,Matrix now)
157 {
158     Matrix ww;
159     ww.ini();
160     for(LL i=1;i<=4;i++)
161     for(LL k=1;k<=4;k++)
162     if(cur.mat[i][k])
163     {
164         for(LL j=1;j<=4;j++)
165         if(now.mat[k][j])
166         {
167             ww.mat[i][j]+=cur.mat[i][k]*now.mat[k][j];
168             if(ww.mat[i][j]>=mod)
169             ww.mat[i][j]%=mod;
170         }
171     }
172     return ww;
173 }
174 
175 void power_sum2(LL n)
176 {
177       M_tom.first_ini();//!!
178       LL cnt=0;
179       while(n)
180       {
181           if(n&1)
182           {
183               M_tom=Multiply(M_hxl[cnt],M_tom);
184           }
185           n=n>>1;
186           cnt++;//模拟二进制.
187       }
188       LL sum=0;
189       sum=(sum+M_tom.mat[1][1]*4)%mod;
190       sum=(sum+M_tom.mat[1][2]*5)%mod;
191       sum=(sum+M_tom.mat[1][3]*3)%mod;//!!!开始时没有加
192       sum=(sum+M_tom.mat[1][4]*1)%mod;//!!!开始时没有加
193       printf("%I64d\n",sum);
194 }
195 
196 void pripare()
197 {
198     LL i;
199     M_hxl[0].init();
200     for(i=1;i<32;i++)
201     M_hxl[i]=Multiply(M_hxl[i-1],M_hxl[i-1]);
202 }
203 
204 int main()
205 {
206     LL T,n,i;
207     pripare();//打表。
208     while(scanf("%I64d",&T)>0)
209     {
210         for(i=1;i<=T;i++)
211         {
212             scanf("%I64d",&n);
213             printf("Case %I64d: ",i);
214             if(n==0)printf("1\n");
215             else if(n==1) printf("4\n");
216             else if(n==2) printf("9\n");
217             else
218             {
219                 power_sum2(n-1);
220             }
221         }
222     }
223     return 0;
224 }

 

posted @ 2013-08-29 16:22  芷水  阅读(284)  评论(0编辑  收藏  举报