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 }