UVALive 7721 K - 2-ME Set 集合dp,所有数的位或来表示状态。

/**
题目:UVALive 7721 K - 2-ME Set
链接:https://vjudge.net/problem/UVALive-7721
题意:给定n个数,从中取出一个集合,至少包含两个元素,如果集合内任意两个元素取位与都是0,那么是合法集合。
如果5个数为{5,2,2,1,4}那么有9种。(5, 2), (5, 2), (2, 1), (2, 1, 4), (2, 4), (2, 1), (2, 1, 4), (2, 4), and (1, 4).
问最多有多少种合法集合。
思路:定义dp[i]表示构成集合i的方法数。注意这里的i不是状态压缩那种i,就是纯粹集合内所有的数都满足任意取位与为0,所有数位或起来的。
因为每个数大小最多为20000,从1到20000取位或发现最大为32767。所以dp数组大小为32770.

dp[i] += dp[j];(j<i,(j&(i-j))==0) 逆序枚举j。

为了优化时间,相同的数自身和自身不可能在同一个集合,所以统一处理。
然后最终计算结果减去所有的单位集合,即每一个数作为一个集合的情况。

*/

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
using namespace std;
typedef pair<int,int> P;
typedef long long LL;
const int N = 2e4+10;
const int M = 15;
const int mod = 1e9+7;
const int INF = 0x3f3f3f3f;
int a[N], dp[32770], s[N], num[N];
struct node
{
    int value, cnt;
}t[N];
vector<node> v;
int main()
{
    int T, cas = 1, n;
    cin>>T;
    while(T--)
    {
        scanf("%d",&n);
        memset(num, 0, sizeof num);
        for(int i = 1; i <= n; i++){
            scanf("%d",&a[i]);
            num[a[i]]++;
        }
        int m = n;
        int n = 0;
        for(int i = 1; i <= 20000; i++){
            if(num[i]){
                t[n].cnt = num[i];
                t[n].value = i;
                n++;
            }
        }
        memset(dp, 0, sizeof dp);
        dp[0] = 1;
        //v.clear();
        //v.push_back(node{0,1});
        for(int i = 0; i < n; i++){
            if(i==0) s[i] = t[i].value;
            else s[i] = s[i-1]|t[i].value;
        }
        for(int i = 0; i < n; i++){
            for(int j = s[i]; j >= t[i].value; j--){
                if((t[i].value&(j-t[i].value))==0)
                    dp[j] = (dp[j]+(LL)dp[j-t[i].value]*t[i].cnt%mod)%mod;
            }
        }
        int ans = 0;
        for(int i = 1; i <= s[n-1]; i++) ans = (ans+dp[i])%mod;
        printf("Case #%d: %d\n",cas++,(ans-m+mod)%mod);
    }
    return 0;
}

 

posted on 2017-08-01 10:40  hnust_accqx  阅读(189)  评论(0)    收藏  举报

导航