zoukankan      html  css  js  c++  java
  • [9.27模拟] 异或

    题意:多组询问,每组询问给出一段区间[l,r]和一个数k,要求从[l,r]中选择不多于k个数,使得它们的异或和最小,输出最小的异或和、选取的数的个数,选取的数

    题解:

    大力分类讨论一波

    1、k==1,sum=l

    2、k==2,如果r==l+1,则sum=min(l,l^r),否则就是1

    3、k==3,答案不会超过1,现在考虑找出三个数使得其异或和为0,设$x=2^{k-1}-1$,$y=2^{k-1}+2^k$,$z=y-1$,枚举k,若能在$[l,r]$中找到这个三个数,则sum=0

    4、k==4,若r-l>=4,则若l为偶数,l^(l+1)^(l+2)^(l+3)=0,否则(l+1)^(l+2)^(l+3)^(l+4)=0,若r-l<4,则暴搜枚举子集即可

    5、k>=5 sum=0

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<cmath>
      7 #define ll long long
      8 #define xx ((1ll<<k)-1)
      9 #define yy ((1ll<<(k-1))+(1ll<<k)-1)
     10 #define zz ((1ll<<(k-1))+(1ll<<k))
     11 using namespace std;
     12 
     13 int T,a[10];
     14 
     15 struct Node {
     16   int cnt;
     17   ll sum,s[10];
     18 }ans;
     19 
     20 void solve(ll l, ll r) {
     21   bool flg=0;
     22   for(int k=1; zz<=r; k++) {
     23     if(xx>=l) {
     24       printf("0 3
    %lld %lld %lld
    ", (ll)xx,(ll)yy,(ll)zz);
     25       flg=1;
     26       break;
     27     }
     28   }
     29   if(!flg) {
     30     if((l&1ll)==0) printf("1 2
    %lld %lld
    ", l,l+1);
     31     else printf("1 2
    %lld %lld
    ", l+1,l+2);
     32   } 
     33 }
     34 
     35 void cal(Node &res, int deep, ll l) {
     36   Node ret;
     37   ret.sum=ret.cnt=0;
     38   for(int i=1; i<=deep; i++) {
     39     if(a[i]) {
     40       ret.sum^=(l+i-1);
     41       ret.cnt++;
     42       ret.s[ret.cnt]=(l+i-1);
     43     }
     44   }
     45   if(ret.sum<res.sum) res=ret;
     46 }
     47 
     48 void dfs(int dep, int deep, ll l) {
     49   if(dep==deep+1) {
     50     bool flg=0;
     51     for(int i=1; i<=dep; i++) {
     52       if(a[i]!=0) flg=1;
     53     }
     54     if(!flg) return;
     55     cal(ans,deep,l);
     56     return;
     57   }
     58   a[dep]=0,dfs(dep+1,deep,l);
     59   a[dep]=1,dfs(dep+1,deep,l);
     60 }
     61 
     62 void solve2(ll l, ll r) {
     63   ans.sum=1ll<<60,ans.cnt=0;
     64   memset(ans.s,0,10);
     65   dfs(1,r-l+1,l);
     66   printf("%lld %d
    ", ans.sum,ans.cnt);
     67   for(int i=1; i<ans.cnt; i++) {
     68     printf("%lld ", ans.s[i]);
     69   }
     70   printf("%lld
    ", ans.s[ans.cnt]);
     71 }
     72 
     73 int main() {
     74   scanf("%d", &T);
     75   while(T--) {
     76     ll l,r; int k;
     77     scanf("%lld%lld%d", &l,&r,&k);
     78     if(k==1) printf("%lld 1
    %lld
    ", l,l);  
     79     else if(k==2) {
     80       if(r==l+1) {
     81     if(l<=(l^r)) printf("%lld 1
    %lld
    ",l,l);
     82     else printf("%lld 2
    %lld %lld
    ",l^r,l,r);
     83       }      
     84       else {
     85     if((l&1ll)==0) printf("1 2
    %lld %lld
    ", l,l+1);
     86     else printf("1 2
    %lld %lld
    ", l+1,l+2);    
     87       } 
     88     }
     89     else if(k==3) solve(l,r);
     90     else if(k==4) {
     91       if(r-l>=4) {
     92     if((l&1ll)==0) printf("0 4
    %lld %lld %lld %lld
    ", l,l+1,l+2,l+3);    
     93     else printf("0 4
    %lld %lld %lld %lld
    ", l+1,l+2,l+3,l+4);
     94       }
     95       else solve2(l,r);
     96     }
     97     else {
     98       if((l&1ll)==0) printf("0 4
    %lld %lld %lld %lld
    ",l,l+1,l+2,l+3);
     99       else printf("0 4
    %lld %lld %lld %lld
    ", l+1,l+2,l+3,l+4);
    100     }
    101   }
    102   return 0;
    103 }
  • 相关阅读:
    jquery学会的
    oracle技巧-持续更新
    c语言技巧--长期更新
    2019暑假集训 最大子树和
    2019暑假集训 细胞分裂
    2019暑假集训 金明的预算方案
    2019暑假集训 能量项链
    2019暑假集训 神经网络
    0023-特殊的方程
    0022-并联电阻
  • 原文地址:https://www.cnblogs.com/HLXZZ/p/7612674.html
Copyright © 2011-2022 走看看