hdu4901 多校4 1005

呵呵呵呵 ,做这道题的时候完全没有想到使用dp去做的,想的仅仅只是暴力= =,我的脑子里面装的都是些什么啊

好了,不多说乖乖写题解,这道题的题意是:给你a1~an n个数,要分成两个集合s和t,t里面每个数的下标都要大于s

要你求出,s里所有元素异或后得到的值等于t里面所有元素与的值得情况有多少种。

分析:赛后看题解,发现他写的是送分题 我的泪都要崩出来了。。。

用 gao1【i】【j】记录从0到i异或得到值得总数

用 gao2【i】【j】记录从i到n-1与的值得总数

用 gao3【i】【j】记录从i到n-1的元素,且一定包含a[i],AND得到j的种类数。

最后将gao1【i】【j】*gao3【i】【j】的和加起来求模就行了

#include<cstdio>
#include<cstring>

typedef __int64 LL;
#define mod 1000000007
const int MAXN = 1002;
const int MAXA = 1025;
int gao1[MAXN][MAXA], gao2[MAXN][MAXA], gao3[MAXN][MAXA];
int a[MAXN];

int main()
{
    int T, n, i, j, t;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(i = 0; i < n; i++)
            scanf("%d",&a[i]);
        memset(gao1, 0, sizeof(gao1));
        memset(gao2, 0, sizeof(gao2));
        memset(gao3, 0, sizeof(gao3));
        gao1[0][a[0]] = 1;
        for(i = 1; i < n - 1; i++)
        {
            gao1[i][a[i]]++; //单独一个元素构成一个集合
            for(j = 0; j < MAXA; j++)
            {
                if(gao1[i-1][j])
                {
                    gao1[i][j] += gao1[i-1][j]; //不添加第i个元素进行异或,继承之前算好的
                    gao1[i][j] %= mod;

                    t = j ^ a[i];  //添加第i个元素进行异或
                    gao1[i][t] += gao1[i-1][j];
                    gao1[i][t] %= mod;
                }
            }
        }
        gao2[n-1][a[n-1]] = 1;
        gao3[n-1][a[n-1]] = 1;
        for(i = n-2; i > 0; i--)
        {
            gao2[i][a[i]]++;
            gao3[i][a[i]]++;   //单独一个元素构成一个集合
            for(j = 0; j < MAXA; j++)
            {
                if(gao2[i+1][j])
                {
                    gao2[i][j] += gao2[i+1][j];  //不添加第i个元素进行按位与
                    gao2[i][j] %= mod;

                    t = j & a[i]; //添加第i个元素进行按位与
                    gao2[i][t] += gao2[i+1][j];
                    gao2[i][t] %= mod;

                    gao3[i][t] += gao2[i+1][j]; //添加第i个元素进行按位与
                    gao3[i][t] %= mod;
                }
            }
        }
        int ans = 0;
        for(i = 0; i < n - 1; i++)
        {
            for(j = 0; j < MAXA; j++)
            {
                if(gao1[i][j] && gao3[i+1][j])
                {
                    ans += (LL(gao1[i][j]) * gao3[i+1][j] % mod);
                    ans %= mod;
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值