题意:
g(i)=k*i+b;
f(0)=0
f(1)=1
f(n)=f(n-1)+f(n-2) (n>=2)
让你求:sum(f(g(i)))for 0<=i<n
题解:
S(g(i))
= F(b) + F(b+k) + F(b+2k) + .... + F(b+nk)
// 设 A = {1,1,0,1}, (花括号表示矩阵...)
// 也就是fib数的变化矩阵,F(x) = (A^x) * {1,0}
= F(b) + (A^k)F(b) + (A^2k)F(b)+….+(A^nk)F(b)
// 提取公因式 F(b)
= F(b) [ E +A^k + A^2k + ….+ A^nk] // (E表示的是单位矩阵)
// 令 K = A^k 后
E +A^k + A^2k + ….+ A^nk 变成 K^0+K^1+K^2+…+K^n
这里用到二分等比求和
1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int i=a;i<=b;++i) 4 using namespace std; 5 typedef long long ll; 6 7 const int mat_N=2; 8 int mo; 9 struct mat{ 10 ll c[mat_N][mat_N]; 11 void init(){mst(c,0);} 12 mat operator*(mat b){ 13 mat M;int N=mat_N-1;M.init(); 14 F(i,0,N)F(j,0,N)F(k,0,N)M.c[i][k]=(M.c[i][k]+c[i][j]*b.c[j][k])%mo; 15 return M; 16 } 17 mat operator+(mat b){ 18 mat M;int N=mat_N-1; 19 F(i,0,N)F(j,0,N)M.c[i][j]=(c[i][j]+b.c[i][j])%mo; 20 return M; 21 } 22 mat operator^(ll k){ 23 mat ans,M=(*this);int N=mat_N-1;ans.init(); 24 F(i,0,N)ans.c[i][i]=1; 25 while(k){if(k&1)ans=ans*M;k>>=1,M=M*M;} 26 return ans; 27 } 28 }A,B,C,E; 29 30 // 等比二分求和(a+a^2+a^3+...+a^n) 31 mat calc(mat a, int n) { 32 if (n==1)return a; 33 if (n&1)return (a^n)+calc(a,n-1); 34 return calc(a, n/2)*((a^(n/2))+E); 35 } 36 37 int k,b,n; 38 39 int main() 40 { 41 A=(mat){1,1,1,0}; 42 E=(mat){1,0,0,1}; 43 while(~scanf("%d%d%d%d",&k,&b,&n,&mo)) 44 { 45 B=A^k; 46 C=calc(B,n-1)+(A^0); 47 C=(A^b)*C; 48 printf("%lld ",C.c[0][1]); 49 } 50 return 0; 51 }