zoukankan      html  css  js  c++  java
  • HDU 4901 DP

    我觉得这个DP挺难的。。。然而这只是lydrainbowcat学长幻灯片上的第一题……
    明天考试要GG。
    题意:
    给你一个序列,让你选出两个集合S和T。保证S里的数都在T里的数的左边。求一共有多少个集合满足S的异或所得等于T的与的所得,并mod一个大素数。
    思路:
    上课讲的DP,可惜我写了一晚上。。。。。。
    首先我们可以枚举断点。i
    这样就把序列分成了两部分。
    前半部分是集合S
    可以进行DP
    j表示前i个数xor得j的方案数
    f[i][j]=(f[i-1][j]+f[i-1][j*a[i]])%mod
    (上一个状态和a[i]进行异或操作)
    后半部分是集合T
    也可以进行DP
    j表示进行与操作得j的方案数
    d[i][j]=d[i+1][j]
    (显然,如果上一个状态可以到j,这个状态也可以)
    d[i][j]=d[i+1][j],d[i][j&a[i]]=(d[i+1][j]+d[i][j&a[i]])%mod;
    (上一个状态和a[i]进行位与操作)
    所以 ans=((long long)f[i-1][j^a[i]]*d[i+1][j]+ans)%mod;
    (要有强制类型转换)

    // by SiriusRen
    #include <bits/stdc++.h>
    #define F for(int j=0;j<1024;j++)
    using namespace std;
    int cases,n,a[1001],f[1001][1025],d[1001][1025],mod=1e9+7,ans;
    int main(){
        scanf("%d",&cases);
        while(cases--){
            memset(f,0,sizeof(f)),memset(d,0,sizeof(d)),ans=0;
            scanf("%d",&n);
            for(int i=1;i<=n;i++)scanf("%d",&a[i]),d[i][a[i]]++;
            f[0][0]=1;
            for(int i=1;i<=n;i++)
                for(int j=0;j<1024;j++)f[i][j]=(f[i-1][j^a[i]]+f[i-1][j])%mod;
            for(int i=n-1;i>=1;i--){
                F d[i][j]=d[i+1][j],d[i][j&a[i]]=(d[i+1][j]+d[i][j&a[i]])%mod;
                d[i][a[i]]++;
                F ans=((long long)f[i-1][j^a[i]]*d[i+1][j]+ans)%mod;
            }
            printf("%d
    ",ans);
        }
    }

    一不小心还刷了Code Length的第一。
    这里写图片描述

  • 相关阅读:
    比特币搬砖对冲策略Python源码
    30行JavaScript代码实现一个比特币量化策略
    JBOSS EJB发布WebService
    位运算小练习(1)
    第二周作业
    第一周作业
    CentOS虚拟机NAT方式无法上网
    go语言实现排序算法
    Ubuntu更换科大源
    将Windows下的文件同步到Linux下
  • 原文地址:https://www.cnblogs.com/SiriusRen/p/6532433.html
Copyright © 2011-2022 走看看