其他分享
首页 > 其他分享> > 8.22

8.22

作者:互联网

BZOJ3687 简单题

/*
reference:
    https://www.cnblogs.com/zwfymqz/p/8696499.html
solution:
    我们先分析异或的性质,偶个相同的数异或起来就是零,奇数个异或起来就是那个数本身,
    所以我们只需要用bitset统计每个和出现了奇数次还是偶数次。每次新加入一个数x的时候,我们只需将bitset
    左移x位就可以表示加上x后的集合,然后与原来的bitset异或一下就可以更新。
    这是因为如果某元素之前出现过,这次又出现了,两次的值都为1,那么这个元素就出现了奇数次,异或起来就变成了0
    ;在两个bitset中只出现了一次,那么1异或0就变成了1;同理,两次都没出现结果也是0。
trigger:
    异或,就是对二进制每一位进行不进位操作
    bitset比DP的空间复杂度更优 
note:
    *bitset 和 异或操作 维护一个数的出现次数是奇数还是偶数 
date:
    2019.08.22
happy:
    体验一波二进制的强大,顺便练练bitset。
*/

bitset<200010>bit; 
int ans,sum,n;

signed main(){
    bit[0]=1;
    rd(n);
    rep(i,1,n){
        int x;rd(x);
        sum+=x;
        bit^=bit<<x;
    }
    dwn(i,sum,1){
        if(bit[i]&1)
            ans^=i;
    }
    printf("%d",ans);
    return 0;
}
/*
2
1 3
*/
//6

【前缀和 枚举顺序】P3131 [USACO16JAN]子共七Subsequences Summing to Sevens

/*
translation:
    n个数,分别是a[1...n]
    求一个最长的区间[x,y],使得区间中的数(a[x...y])的和能被7整除。输出区间长度。若没有符合要求的区间,输出0。 
reference:
    
solution:
    (结论题,若sum[i]==sum[j] ,则sum[k]-sum[i]%7==0)
    用sum[i]表示前缀和%7的值,若存在i<=j满足sum[j]=sum[i],则区间(i,j]的和为7的倍数。
trigger:
    显然,这是一个前缀和问题, 
note:
    *
date:
    2019.08.22
happy:
    */

#define N 50010
#define M 

int first[7],sum[N],last[7]={INT_MIN},a[N];
int maxx=INT_MIN,n;

signed main(){
    rd(n);
    rep(i,1,n){
        rd(a[i]);
        sum[i]=(sum[i-1]+a[i])%7; 
    }
    dwn(i,n,1)//倒序枚举,保证最后一次更新时first最小 
        first[sum[i]]=i;
    rep(i,1,n)//正序枚举,保证最后一次更新时last最大 
        last[sum[i]]=i;
    rep(i,0,6){
        maxx=max(maxx,last[i]-first[i]);
    }
    printf("%lld",maxx);
    return 0;
}
/*
7
3
5
1
6
2
14
10
*/
//5

P1967 货车运输

/*
reference:
    
solution:
    首先,有一些边权比较小的边我们永远都不会取到,考虑把他们删掉,而整个图又要联通,
    那么就建一个最大生成树!两点之间的路径用lca维护,于是问题就转化为:
    在最大生成树的新图上跑lca,并同时维护这条路径的最小边权,最小边权也可以采用
    倍增的方法一道求出 
trigger:
    
note:
    *t=log2(n)+1 
date:
    2019.08.22
happy:
    
*/

标签:last,sum,rd,异或,bitset,8.22,first
来源: https://www.cnblogs.com/sjsjsj-minus-Si/p/11635379.html