2014 Multi-University Training Contest 4小记

1005

typedef  long  long  LL ;

const  LL   mod = 1000000007LL ;
const  int  maxn =  1<<11 ;
LL     dp[1002][maxn]  , dp1[1002][maxn] ,  dp2[1002][maxn] ;
int    a[1002] ;

int   main(){
      int  n  , i ,  j  , t , c  ;
      cin>>t ;
      while(t--){
            cin>>n ;
            for(i = 1 ; i <= n ; i++)  scanf("%d" , &a[i]) ;
            memset(dp , 0  , sizeof(dp))  ;
            memset(dp1, 0 , sizeof(dp1))  ;
            for(i = 1 ; i <= n ; i++){
               for(j = 0  ; j < maxn ; j++) dp1[i][j] = dp1[i-1][j] ;
               for(j = 0  ; j < maxn ; j++){
                   c = j ^ a[i] ;
                   dp1[i][c] += dp1[i-1][j] ;
                   if(dp1[i][c] >= mod) dp1[i][c] %= mod ;
               }
               dp1[i][a[i]]++ ;

               for(j = 0 ; j < maxn ; j++){
                    c = j ^ a[i] ;
                    dp[i][c] += dp1[i-1][j] ;
                    if(dp[i][c] >= mod) dp[i][c] %= mod ;
               }
               dp[i][a[i]]++ ;
            }

            memset(dp2 , 0 , sizeof(dp2)) ;
            for(i = n ; i >= 1 ; i--){
                for(j = 0 ; j < maxn ; j++)
                    dp2[i][j] = dp2[i+1][j] ;
                for(j = 0 ; j < maxn ; j++){
                    c = j & a[i] ;
                    dp2[i][c] += dp2[i+1][j] ;
                    if(dp2[i][c] >= mod) dp2[i][c] %= mod ;
                }
                dp2[i][a[i]]++ ;
            }

            LL  sum = 0LL   , s  ;
            for(i = 1 ; i <= n ; i++){
                 for(j = 0 ; j < maxn ; j++){
                       s = dp[i][j] * dp2[i+1][j] ;
                       if(s >= mod)  s %= mod ;
                       sum += s ;
                       if(sum >= mod) sum %= mod;
                 }
            }

            printf("%I64d\n" , sum) ;
      }
      return 0 ;
}

1006


int    gcd(int  x  ,  int  y){
       return  y ==  0 ?  x : gcd(y , x % y) ;
}

const   int  maxn  =  100008 ;

int    color[maxn<<2]  ;
int    x[maxn]  ;


void   up(int t){
       if(color[t<<1] == color[t<<1|1])  color[t] = color[t<<1] ;
       else  color[t] = -1 ;
}

void   down(int t){
       if(color[t] != -1){
             color[t<<1] = color[t<<1|1] = color[t] ;
             color[t] = -1 ;
       }
}


void   make(int  l , int r , int t){
       if(l == r){
             color[t] = x[l]  ;
             return  ;
       }
       int m = (l + r) >> 1 ;
       make(l  ,  m , t<<1) ;
       make(m+1 , r , t<<1|1) ;
       up(t) ;
}

void   update(int L , int  R  , int  c ,  int  l , int r , int t){
       if(L <= l  &&  r <= R ||  l == r){
             color[t] = c  ;
             return  ;
       }
       down(t) ;
       int  m = (l  +  r) >> 1  ;
       if(L <= m)  update(L , R , c , l , m  ,  t<<1) ;
       if(R > m)   update(L , R , c , m+1 , r , t<<1|1) ;
       up(t) ;
}

void   update2(int L , int  R  , int  c ,  int  l , int r , int t){
       if(l == r && color[t] > c){
              color[t] = gcd(color[t] , c) ;
              return  ;
       }
       if(L <= l  &&  r <= R){
             if(color[t] != -1){
                    if(color[t] > c) color[t] = gcd(color[t] , c) ;
                    return  ;
             }
             else{
                    int  m = (l  +  r) >> 1  ;
                    if(L <= m)  update2(L , R , c , l , m  ,  t<<1) ;
                    if(R > m)   update2(L , R , c , m+1 , r , t<<1|1) ;
                    up(t) ;
             }
             return  ;
       }
       down(t) ;
       int  m = (l  +  r) >> 1  ;
       if(L <= m)  update2(L , R , c , l , m  ,  t<<1) ;
       if(R > m)   update2(L , R , c , m+1 , r , t<<1|1) ;
       up(t) ;
}

void   ask(int l  , int  r , int t){
       if(color[t] != -1){
            for(int i = l ; i <= r ; i++)  x[i] = color[t] ;
            return  ;
       }
       down(t) ;
       int  m = (l  +  r) >> 1 ;
       ask(l , m , t<<1) ;
       ask(m+1 , r , t<<1|1) ;
}

int   main(){
      int t , n , i , m  , k , l , r , c ;
      cin>>t ;
      while(t--){
           cin>>n ;
           for(i = 1 ; i <= n ; i++)  scanf("%d" , &x[i]) ;
           make(1 , n , 1) ;
           cin>>m ;
           while(m--){
                scanf("%d%d%d%d" , &k,&l,&r,&c) ;
                if(l > r) swap(l , r) ;
                if(k == 1)  update(l , r , c , 1 , n , 1 ) ;
                else        update2(l , r , c , 1 , n , 1 ) ;
           }
           ask(1 , n , 1) ;
           for(i = 1 ; i <= n ; i++)  printf("%d " , x[i]) ;
           puts("") ;
      }
      return  0  ;
}

1010

typedef  long  long  LL ;

const   LL   mod   =  1000000007LL ;
const   int  maxn  =  1<<20 + 1 ;

LL   dp[maxn]  ;

int  main(){
     int  t , n , k , l , i , j  , limt  ;
     cin>>t ;
     while(t--){
          scanf("%d%d%d" , &n , &k , &l) ;
          LL  c =  0LL ;
          limt = (1<<k) - 1 ;
          if(l > k){
              c = (LL)(l - k) ;
              l =  k ;
          }
          memset(dp , 0 , sizeof(dp)) ;
          dp[0] = 1LL  ;
          while(n--){
               for(i = limt ; i >= 0 ; i--){
                   if(! dp[i])  continue  ;
                   int from = dp[i] ;
                   LL  next = dp[i] * c % mod ;
                   for(j = 1 ; j <= l ; j++){
                        //每种可能状态都加上j  i左移j位,超出的变0, 再在(j-1)为加1
                        //不选择 j , 状态就是 i 
                        //转移状态就是这2种情况     
                        int to = i | (1<<(j-1)) | ((i<<j) & limt) ;
                        dp[to] += from  ;
                        if(dp[to] >= mod)  dp[to] %= mod ;
                   }
                   //加(k , L] 的情况,状态不会改变,如果选择此数组成方案多next
                   dp[i] += next ;  
                   if(dp[i] >= mod)  dp[i] %= mod ;
               }
          }
          LL  sum = 0 ;
          for(i = 0 ; i <= limt ; i++){
               if(i & (1<<(k-1))){
                    sum += dp[i] ;
                    if(sum >= mod)  sum %= mod;
               }
          }
          printf("%I64d\n"  , sum)  ;
     }
     return  0 ;
}


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值