Codeforces Round #258 (Div. 2) C, D

n场比赛,k场结果已知,其中, |a赢的次数 - b赢的次数| = k1 ,  |c赢的次数 - d赢的次数| = k2 

求是否存在方案使得,a,b,c,d赢的次数相同。

f(x)记x赢的次数

有 f(a) + f(b) + f(c) + f(d) = k 

   |f(a) - f(b)| = d1 

   |f(c) - f(d)| = d2 

三个方程三个未知数,且系数矩阵行列式不为0,存在唯一解。

若某解 > n/3  则没有这样的方案 


typedef long long  LL ;


LL n , k , d1 , d2 ;

LL    A(LL a[4][4]){
      return a[1][1]*a[2][2]*a[3][3]
           + a[1][2]*a[2][3]*a[3][1]
           + a[1][3]*a[2][1]*a[3][2]
           - a[1][3]*a[2][2]*a[3][1]
           - a[1][2]*a[2][1]*a[3][3]
           - a[1][1]*a[3][2]*a[2][3] ;
}

int   gao(LL a[4][4] , LL y[4]){
      LL mu = A(a) ;
      LL b[4][4]  , zi  ;
      LL x ;
      for(int i = 1 ; i <= 3 ; i++){
          for(int j = 1 ; j <= 3 ; j++) b[i][j] = a[i][j] ;
      }
      for(int i = 1 ; i <= 3 ; i++) b[i][1] = y[i] ;
      zi = A(b) ;
      if(zi % mu )  return  0 ;
      x = zi / mu ;
      if(x > n || x < 0)  return 0 ;

      for(int i = 1 ; i <= 3 ; i++){
          for(int j = 1 ; j <= 3 ; j++) b[i][j] = a[i][j] ;
      }
      for(int i = 1 ; i <= 3 ; i++) b[i][2] = y[i] ;
      zi = A(b) ;
      if(zi % mu )  return  0 ;
      x = zi / mu ;
      if(x > n || x < 0)  return 0 ;

      for(int i = 1 ; i <= 3 ; i++){
          for(int j = 1 ; j <= 3 ; j++) b[i][j] = a[i][j] ;
      }
      for(int i = 1 ; i <= 3 ; i++) b[i][3] = y[i] ;
      zi = A(b) ;
      if(zi % mu )  return  0 ;
      x = zi / mu ;
      if(x > n || x < 0)  return 0 ;

      return  1 ;
}

int   main(){
      int t ; cin>>t  ;
      LL a[4][4]  , y[4] ;
      while(t--){
          cin>>n>>k>>d1>>d2 ;
          if(n % 3){
                puts("no") ;
                continue  ;
          }
          n /= 3 ;
          a[1][1] = 1 , a[1][2] = 1 ,  a[1][3] = 1 ;
          a[2][1] = 1 , a[2][2] = -1 , a[2][3] = 0 ;
          a[3][1] = 0 , a[3][2] = 1 , a[3][3] = -1 ;
          y[1] = k , y[2] = d1 , y[3] = d2 ;
          if(gao(a , y) ){
               puts("yes") ;
               continue  ;
          }

          y[1] = k , y[2] = -d1 , y[3] = d2 ;
          if(gao(a , y) ){
               puts("yes") ;
               continue  ;
          }

          y[1] = k , y[2] = d1 , y[3] = -d2 ;
          if(gao(a , y) ){
               puts("yes") ;
               continue  ;
          }

          y[1] = k , y[2] = -d1 , y[3] = -d2 ;
          if(gao(a , y) ){
               puts("yes") ;
               continue  ;
          }

          puts("no")  ;
      }
      return  0  ;
}


D  

连续相同的字母可以压缩为这个字母 , 如abbbbba  压缩后为aba

求串的子串,满足压缩后为回文串。  这样的字串长度为奇数,偶数 的总数。


某串压缩之后一定为abababab...

或者 babababa....

我们字需要统计奇数位,偶数位上 a , b 出现的次数

那么子串为偶数, 只需 奇数位a 取一个  *   偶数位a取一个  

+  奇数位b 取一个  *   偶数位b取一个

子串为奇数数, 只需 奇数位a 取2个   总数

+   偶数位a取2个   总数

+  奇数位b 取2个   总数

+ 偶数位b取2个 总数

+ 串长

typedef  long  long  LL ;
const  int  maxn = 100008 ;
char   str[maxn] ;
LL    c[2][2]  ;
LL    g(LL x){
      return   x >= 2 ? x * (x-1) / 2 : 0 ;
}

int   main(){
      while(scanf("%s" , str+1) != EOF){
           LL n = strlen(str+1) ;
           memset(c , 0 , sizeof(c)) ;
           for(LL i = 1 ; i <= n ; i++)
               c[i&1][str[i] - 'a']++ ;
           LL  a = c[1][0] * c[0][0] + c[1][1] * c[0][1] ;
           LL  b = g(c[0][0]) + g(c[0][1]) + g(c[1][0]) + g(c[1][1])  +  n ;
           cout<< a << " " << b << endl ;
      }
      return  0  ;
}







 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值