我想说,这个题真的很好很好,感谢出题人让我再一次见识了..............
typedef long long LL ; const int Mod = 1000000007 ; struct Mat{ LL a[2][2] ; Mat(){ memset(a , 0 , sizeof(a)) ; } Mat(LL a01){ a[0][0] = 1 , a[0][1] = a01 ; a[1][0] = 1 , a[1][1] = 0 ; } Mat operator * (const Mat &other){ Mat ans ; for(int i = 0 ; i < 2 ; i++){ for(int j = 0 ; j < 2 ; j++){ for(int k = 0 ; k < 2 ; k++){ ans.a[i][j] = (ans.a[i][j] + a[i][k] * other.a[k][j]) % Mod ; } } } return ans ; } }; const int Max_N = 100008 ; Mat sum[Max_N<<2] ; LL x[Max_N] ; int N ; void make_tree(int L , int R , int root){ if(L == R){ sum[root] = Mat(x[L]) ; return ; } int mid = (L + R) >> 1 ; make_tree(L , mid , root<<1) ; make_tree(mid+1 , R , root<<1|1) ; sum[root] = sum[root<<1|1] * sum[root<<1] ; } Mat query(int l , int r , int L , int R , int root){ if(l <= L && R <= r) return sum[root] ; int mid = (L + R) >> 1 ; if(r <= mid) return query(l , r , L , mid , root<<1) ; else if(l > mid) return query(l , r , mid+1 , R , root<<1|1) ; else return query(l , r , mid+1 , R , root<<1|1) * query(l , r , L , mid , root<<1) ; } LL Ans(int L , int R){ if(L > R) swap(L , R) ; if(R == L || R == L + 1) return x[R] % Mod ; Mat m = query(L+2 , R , 1 , N , 1) ; return (m.a[0][0] * x[L+1] + m.a[0][1] * x[L]) % Mod ; } int main(){ int T , M , i , l , r ; cin>>T ; while(T--){ scanf("%d%d" ,&N ,&M) ; for(i = 1 ; i <= N ; i++) scanf("%lld" , &x[i]) ; make_tree(1 , N , 1) ; while(M--){ scanf("%d%d" ,&l ,&r) ; printf("%lld\n" , Ans(l ,r)) ; } } return 0 ; }
zoj 1671
int Mod ; struct Mat{ int elem[3][3] ; Mat(){ memset(elem , 0 , sizeof(elem)) ; } void DiaOne(){ elem[1][1] = elem[2][2] = 1 ; } void read(){ scanf("%d%d%d%d" , &elem[1][1] ,&elem[1][2] , &elem[2][1] , &elem[2][2]) ; } void out(){ printf("%d %d\n%d %d\n" , elem[1][1] ,elem[1][2] , elem[2][1] , elem[2][2]) ; } }; Mat operator * (Mat a , Mat b){ Mat s ; int i , j , k ; for(i = 1 ; i <= 2 ; i++){ for(j = 1 ; j <= 2 ; j++){ if(a.elem[i][j] == 0) continue ; for(k = 1 ; k <= 2 ; k++){ s.elem[i][k] += a.elem[i][j] * b.elem[j][k] ; s.elem[i][k] %= Mod ; } } } return s ; } const int Max_N = 30008 ; Mat sum[Max_N<<2] , x[Max_N] ; void up(int t){ sum[t] = sum[t<<1] * sum[t<<1|1] ; } void make(int L , int R , int t){ if(L == R){ sum[t] = x[L] ; return ;} int M = (L + R) >> 1 ; make(L , M , t<<1) ; make(M+1 , R , t<<1|1) ; up(t) ; } Mat query(int l , int r , int L , int R , int t ){ if(l <= L && R <= r) return sum[t] ; int M = (L + R) >> 1 ; Mat s ; s.DiaOne() ; if(l <= M) s = s * query(l , r , L , M , t<<1) ; if(r > M) s = s * query(l , r , M+1 , R , t<<1|1) ; return s ; } int main(){ int i , n , m , l , r , T = 0 ; while(scanf("%d%d%d" ,&Mod, &n ,&m) != EOF ){ for(i = 1 ; i <= n ; i++) x[i].read() ; make(1 , n , 1) ; while(m--){ scanf("%d%d" ,&l ,&r) ; if(T++ > 0) puts("") ; query(l , r , 1 , n , 1).out() ; } } return 0 ; }