zoukankan      html  css  js  c++  java
  • 【JZOJ3889】序列问题【dp】【高精度】

    题目:

    题目链接:https://jzoj.net/senior/#main/show/3889
    小H是个善于思考的学生,她正在思考一个有关序列的问题。
    她的面前浮现出了一个长度为n的序列{ai},她想找出两个非空的集合S、T。
    这两个集合要满足以下的条件:
    两个集合中的元素都为整数,且都在 [1, n] 里,即Si,Ti ∈ [1, n]。
    对于集合S中任意一个元素x,集合T中任意一个元素y,满足x < y。
    对于大小分别为p, q的集合S与T,满足 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),你能帮助她吗?


    思路:

    如果满足a[s1] xor a[s2] xor a[s3] ... xor a[sp] = a[t1] and a[t2] and a[t3] ... and a[tq]a[s1] xor a[s2] xor a[s3] ... xor a[sp] = a[t1] and a[t2] and a[t3] ... and a[tq]
    ,那么就等价于前者的异或值与后者的与值异或起来等于0。
    所以设f[i][j][3]f[i][j][3]表示inisim n的数字,异或起来为jj,已经到了 一个都没选 // 与区间 // 异或区间的方案数。
    直接转移即可。
    注意要压位高精。
    时间复杂度O(n×Smax×maxn)O(n imes Smax imes maxn)。其中Smax=1024,maxnSmax=1024,maxn是高精度的位数。


    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    const int N=1001,Smax=1024,MAXN=40;
    int n,a[N];
    
    struct node
    {
    	ll a[MAXN+1];
    }f[2][Smax][3];
    
    node operator +(node a,node b)
    {
    	node c;
    	ll t=0;
    	for (register int k=MAXN;k>=1;k--)
    	{
    		c.a[k]=a.a[k]+b.a[k]+t;
    		t=c.a[k]/100000000;
    		c.a[k]%=100000000;
    	}
    	return c;
    };
    
    int main()
    {
    	scanf("%d",&n);
    	for (register int i=1;i<=n;i++)
    		scanf("%d",&a[i]);
    	f[(n+1)&1][Smax-1][0].a[MAXN]=1;
    	for (register int i=n;i>=1;i--)
    	{
    		int id=i&1;
    		memset(f[id],0,sizeof(f[id]));
    		for (register int j=0;j<Smax;j++)
    		{
    			f[id][j][0]=f[id^1][j][0];
    			f[id][j&a[i]][1]=f[id][j&a[i]][1]+f[id^1][j][1]+f[id^1][j][0];
    			f[id][j^a[i]][2]=f[id][j^a[i]][2]+f[id^1][j][2]+f[id^1][j][1];
    			f[id][j][1]=f[id][j][1]+f[id^1][j][1];
    			f[id][j][2]=f[id][j][2]+f[id^1][j][2];
    		}
    	}
    	int i=1;
    	while (!f[1][0][2].a[i] && i<=MAXN) i++;
    	if (i>MAXN) return !printf("0");
    	printf("%lld",f[1][0][2].a[i]);
    	for (i++;i<=MAXN;i++) printf("%08lld",f[1][0][2].a[i]);
    	return 0;
    }
    
  • 相关阅读:
    菜鸡的Java笔记 第十六
    菜鸡的Java笔记 第十五 this 关键字
    php 数组(2)
    菜鸡的Java笔记 第十四 String 类常用方法
    菜鸡的Java笔记 第十三 String 类的两种实例化方法
    菜鸡的Java笔记 第十二
    php 递推 递归
    bzoj2306 [Ctsc2011]幸福路径
    bzoj3712 [PA2014]Fiolki
    bzoj2958 序列染色
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11997988.html
Copyright © 2011-2022 走看看