zoukankan      html  css  js  c++  java
  • hdu4901 枚举状态(找集合对S(xor) ==T(and))

    题意:
         给你一个串数字,然后让你在这里面挑取两个集合S ,T,集合的要求是
    (1)不能为空
    (2)S集合的所有元素必须在T集合的左边
    (3)S集合的XOR == T集合的AND
         问可以找到多少组这样的集合对。

    思路:
          两种方法,一个是枚举T集合的第一个元素,或者是枚举S集合的最后一个元素,首先我们开四个数组


    sum_xor[1002][2050] 记录从左到右直到第i个节点的时候的j这个数字有多少种可能

    now_xor[1002][2050] 记录从左到右直到第i个节点并且必须选择i这个节点时j出现的次数
    sum_and[1002][2050] 同理.(只不过是n-->1)..
    now_and[1002][2050] 同理. (只不过是n-->1)..


    更新数组的时候可以想象下01背包,当前的状态由上一步的所有可能状态和当前的这个数字组合出来后得到的新状态,对于sum_..记得加上上一步的所有状态,这个题目关键就是枚举的时候不能出现重复的集合对。然后我们枚举一遍就ok了,两种枚举方法,第一种是sum_xor,now_and两个状态组合,另一

    个是now_xor ,sum_and组合,给个关键的代码

    for(i = 1 ;i <= n ;i ++)
    {
        now_xor[i][num[i]] ++;//自己这个状态
        sum_xor[i][num[i]] ++;//自己这个状态
        for(j = 0 ;j <= 2048 ;j ++)
        {
           if(sum_xor[i-1][j])//如果之前有j这个状态
           {
              now_xor[i][j^num[i]] += sum_xor[i-1][j];//新状态的增加值
              sum_xor[i][j^num[i]] += sum_xor[i-1][j];//新状态的增加值
              sum_xor[i][j] += sum_xor[i-1][j];//当前的和也要加上之前的所有可能和
              //然后都MOD一下
            }  
         }

    }


    AND的同理...


    求出来这4个数组之后的两种枚举方法(两种几乎一样)
    (1)枚举T集合的第一个
    for(i = 2 ;i <= n ;i ++)
    {
       for(j = 0 ;j <= 2048 ;j ++)
       if(sum_xor[i-1][j] && now_and[i][j])
       ans = (sum_xor[i-1][j] * now_and[i][j]) % MOD;
    }
    (2)枚举S集合的最后一位
    for(i = 1 ;i <= n - 1 ;i ++)
    {
       for(j = 0 ;j <= 2048 ;j ++)
       if(now_xor[i-1][j] && sum_and[i][j])
       ans = (now_xor[i-1][j] * sum_and[i][j]) % MOD;
    }



    #include<stdio.h>
    #include<string.h>
    
    #define MOD (1000000000 + 7)
    
    __int64 sum_xor[1002][2050] ,now_xor[1002][2050];
    __int64 sum_and[1002][2050] ,now_and[1002][2050];
    __int64 num[1002];
    
    int main ()
    {
       int i ,j ,n ,t;
       scanf("%d" ,&t);
       while(t--)
       {
          scanf("%d" ,&n);
          for(i = 1 ;i <= n ;i ++)
          scanf("%I64d" ,&num[i]);
          memset(sum_xor ,0 ,sizeof(sum_xor));
          memset(now_xor ,0 ,sizeof(now_xor));
          for(i = 1 ;i <= n ;i ++)
          {
             sum_xor[i][num[i]] ++;
             now_xor[i][num[i]] ++;
             for(j = 0 ;j <= 2048 ;j ++)
             if(sum_xor[i-1][j])
             {
                now_xor[i][j^num[i]] += sum_xor[i-1][j];
                sum_xor[i][j^num[i]] += sum_xor[i-1][j];
                sum_xor[i][j] += sum_xor[i-1][j];
                now_xor[i][j^num[i]] %= MOD;
                sum_xor[i][j^num[i]] %= MOD;
                sum_xor[i][j] %= MOD;
             }
          }
          memset(sum_and ,0 ,sizeof(sum_and));
          memset(now_and ,0 ,sizeof(now_and));
          for(i = n ;i >= 1 ;i --)
          {
             sum_and[i][num[i]] ++;
             now_and[i][num[i]] ++;
             for(j = 0 ;j <= 2048 ;j ++)
             if(sum_and[i+1][j])
             {
                now_and[i][j&num[i]] += sum_and[i+1][j];
                sum_and[i][j&num[i]] += sum_and[i+1][j];
                sum_and[i][j] += sum_and[i+1][j];
                now_and[i][j&num[i]] %= MOD;
                sum_and[i][j&num[i]] %= MOD;
                sum_and[i][j] %= MOD;
             }
          }
          __int64 ans = 0;
          for(i = 2 ;i <= n ;i ++)
          {
             for(j = 0 ;j <= 2048 ;j ++)
             if(sum_xor[i-1][j] && now_and[i][j])
             ans = (ans + sum_xor[i-1][j] * now_and[i][j]) % MOD;
          }
          printf("%I64d
    " ,ans);
       }
       return 0;
    }
          
          
          
          
    



  • 相关阅读:
    Java操作XML文件
    数据结构之shell排序
    制作个人开发IDE
    ActiveMQ基本详解与总结
    ActiveMQ的作用总结(应用场景及优势)
    C# 封装miniblink 使用HTML/CSS/JS来构建.Net 应用程序界面和简易浏览器
    已使用.netframework,version=v4.6.1 而不是目标框架netcoreapp,version=v2.1 还原包,此包可能与项目不完全兼容
    RabbitMQ的六种工作模式
    RabbitMQ学习系列
    RabbitMQ基本概念和原理
  • 原文地址:https://www.cnblogs.com/csnd/p/12062865.html
Copyright © 2011-2022 走看看