zoukankan      html  css  js  c++  java
  • 【找规律】【二进制拆分】hdu6129 Just do it

    给你数列a,问你对它作m次求前缀异或和之后的新数列是什么。

    考虑a1对最终生成的数列的每一位的贡献,仅仅考虑奇偶性,

    当m为2的幂次的时候,恰好是这样的

    2^0 1 1 1 1 1 ...

    2^1 1 0 1 0 1...

    2^2 1 3个0 1 3个0 ...

    2^3 1 7个0 1 7个0 ...

    于是,从做了i次操作之后的序列,变换到做了i+2^k次操作之后的序列,可以轻松地通过

    for i = 1 to n-2^k

      a(i+2^k) := a(i+2^k) xor a(i) 【*】

    这样轮求其隔2^k项组成的前缀异或和得到。。。

    于是对m进行二进制拆分,其二进制表示下每一个1对应一次【*】操作。就只需要执行m的二进制表示中1的个数次这样的操作即可。

    附:

    ① C(n,m)为奇数当且仅当(n&m)==m。

    ② n!中因子2的个数等于(n-n的二进制表示中1的个数)。

    ③ 阶乘中的因子个数是可以递推的。

    #include<cstdio>
    using namespace std;
    int n,m,T,a[200005];
    int main(){
    	scanf("%d",&T);
    	for(;T;--T){
    		scanf("%d%d",&n,&m);
    		for(int i=1;i<=n;++i){
    			scanf("%d",&a[i]);
    		}
    		for(int i=0;(1<<i)<=m;++i){
    			if(m&(1<<i)){
    				for(int j=1;j+(1<<i)<=n;++j){
    					a[j+(1<<i)]^=a[j];
    				}
    			}
    		}
    		for(int i=1;i<n;++i){
    			printf("%d ",a[i]);
    		}
    		printf("%d
    ",a[n]);
    	}
    	return 0;
    }
  • 相关阅读:
    [bzoj1095] [ZJOI2007]Hide 捉迷藏
    [bzoj3730] 震波
    [bzoj3672] [Noi2014]购票
    [bzoj4129] Haruna’s Breakfast
    《CSS3知识点》
    《表单总结》
    <表格>
    《HTML总结》
    <java程序大集合>
    《字符串的概念》
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7375903.html
Copyright © 2011-2022 走看看