zoukankan      html  css  js  c++  java
  • JZOJ 3889

    ( ext{Problem})

    小H是个善于思考的学生,她正在思考一个有关序列的问题。
    她的面前浮现出了一个长度为 (n) 的序列 ({ai}),她想找出两个非空的集合 (S、T)
    这两个集合要满足以下的条件:
    两个集合中的元素都为整数,且都在 ([1, n]) 里,即 (Si,Ti ∈ [1, n])
    对于集合 (S) 中任意一个元素 (x),集合 (T) 中任意一个元素 (y),满足 (x < y)
    对于大小分别为 (p, q) 的集合 (S)(T),满足 ( ext{a[s1] xor a[s2] xor a[s3] ... xor a[sp] = a[t1] and a[t2] and a[t3] ... and a[tq]}).
    小H想知道一共有多少对这样的集合 ((S,T)),你能帮助她吗?

    ( ext{Solution})

    显然 (dp)
    一般想到的是 (f_{i,j}) 表示顺着做到 (i) 位异或值为 (j) 的方案数,(g_{i,j}) 则是倒着 (and) 的方案数
    那么枚举临界点计算即可
    但是由于正解要压位高精,占据空间,是得分着做很悬
    于是考虑一个神奇的 (dp)

    注意它的 (j) 表示倒着做 (and) 完后继续那这个值 (xor) 后的 (j)
    所以答案是 (f[p][0][2])
    (p) 表示使用滚动数组最后得到的状态
    转移只要考虑当前位选不选即可

    ( ext{Code})

    #include<cstdio>
    #include<iostream>
    using namespace std;
    
    const int N = 1005, P = 1e8;
    int n, a[N];
    
    struct node{
    	int m[40] = {};
    }f[2][1024][3]; 
    
    inline node operator + (node a, node b)
    {
    	node c;
    	c.m[0] = max(a.m[0], b.m[0]);
    	for(int i = 1; i <= c.m[0]; i++)
    	{
    		c.m[i] += a.m[i] + b.m[i];
    		c.m[i + 1] += c.m[i] / P, c.m[i] %= P;
    	}
    	if (c.m[c.m[0] + 1] > 0) ++c.m[0];
    	return c;
    }
    
    int main()
    {
    	scanf("%d", &n);
    	for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    	f[0][1023][0].m[0] = f[0][1023][0].m[1] = 1;
    	int p = 0;
    	for(int i = n; i; i--)
    	{
    		for(int j = 0; j < 1024; j++) f[p ^ 1][j][0] = f[p][j][0], f[p ^ 1][j][1] = f[p][j][1], 
    									f[p ^ 1][j][2] = f[p][j][2];
    		for(int j = 0; j < 1024; j++)
    		{
    			f[p ^ 1][j & a[i]][1] = f[p ^ 1][j & a[i]][1] + f[p][j][0] + f[p][j][1];
    			f[p ^ 1][j ^ a[i]][2] = f[p ^ 1][j ^ a[i]][2] + f[p][j][2] + f[p][j][1];
    		}
    		p ^= 1;
    	}
    	if (f[p][0][2].m[0] == 0){printf("0
    "); return 0;}
    	printf("%d", f[p][0][2].m[f[p][0][2].m[0]]);
    	for(int i = f[p][0][2].m[0] - 1; i; i--) printf("%08d", f[p][0][2].m[i]);
    }
    
  • 相关阅读:
    基于Maven的MyBatis Generator逆向工程
    JQuery对象调用reset方法:Uncaught TypeError: $(...).reset is not a function
    死锁编码及定位分析
    线程池的简介及底层原理
    转载:Mysql8.0忘记 root 密码, 如何修改?
    synchronized 和 Lock 有什么区别?
    java 中的阻塞队列及生产者-消费者中的简单应用
    java 中 CountDownLatch、CyclicBarrier 和 Semaphore 的简单使用
    java中的公平锁、非公平锁、可重入锁、递归锁、自旋锁、独占锁和共享锁
    Java 集合类的线程安全问题及解决方法
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/14860629.html
Copyright © 2011-2022 走看看