您的位置:首页 > 其它

ZOJ 3772 Calculate the Function (好题,线段树) ZOJ 1671

2014-04-07 10:54 423 查看
我想说,这个题真的很好很好,感谢出题人让我再一次见识了..............



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 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: