SRM601 WinterAndSnowmen

思路:
首先考虑暴力 DP D P dp[i][a][b] d p [ i ] [ a ] [ b ] ={ dp[i1][ai][b],dp[i1][a][bi],dp[i1][a][b] d p [ i − 1 ] [ a ⊕ i ] [ b ] , d p [ i − 1 ] [ a ] [ b ⊕ i ] , d p [ i − 1 ] [ a ] [ b ] } Θ(n3) Θ ( n 3 )
然后优化,首先考虑定义状态 dp[i][ab] d p [ i ] [ a − b ] 这样虽然能反映两个数大小但是不好转移
所以考虑 dp[i][ab] d p [ i ] [ a b ] 这样方便了转移但是·不容易反映大小,所以还要定义一个状态:第一个二进制中的1是在a中取到还是在b中取到,有转移:

if(j<=n) Add(dp[i+1][k^j][(j&(1<<i))?1-l:l],dp[i][k][l]);
if(j<=m) Add(dp[i+1][k^j][l],dp[i][k][l]);
Add(dp[i+1][k][l],dp[i][k][l]);

code:

#include<bits/stdc++.h>
using namespace std;
#define REP(i,f,t)for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define SREP(i,f,t)for(int i=(f),i##_end_=(t);i<i##_end_;i++)
#define DREP(i,f,t)for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define db double
#define LL long long 
#define INF 0x3f3f3f3f
#define Sz(a) sizeof(a)
#define mcl(a,b) memset(a,b,Sz(a))
#define mcp(a,b) memcpy(a,b,Sz(b))
#define pb push_back
template<class T>inline bool chkmin(T &x,T y){return y<x?x=y,1:0;}
template<class T>inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
inline LL Max(LL &x,LL y){return x>y?x:y;}
inline LL Min(LL &x,LL y){return x<y?x:y;}

#define N 2052
#define M 12
#define mod 1000000007

void Add(LL &x,LL y){
    x+=y;
    if(x>=mod)x%=mod;
    if(x<0)(x+=mod)%=mod;
}

LL dp[N][2],tmp[N][2];// dp[i][0/1]表示集合{A}^{B}==i,且0表示最高位在A,1表示最高位在B

class WinterAndSnowmen {
public:
    int getNumber(int n, int m) {
        LL ans=0;
        SREP(i,0,M){
            mcl(dp,0);
            mcl(tmp,0);
            dp[0][0]=1;
            REP(j,1,max(n,m)){
                mcl(tmp,0);
                SREP(k,0,N) REP(l,0,1){
                    if(j<=n)Add(tmp[k^j][(j&(1<<i))?1-l:l],dp[k][l]);
                    if(j<=m)Add(tmp[k^j][l],dp[k][l]);
                }
                SREP(k,0,N) REP(l,0,1) Add(dp[k][l],tmp[k][l]);
            }
            SREP(j,0,N)if(j/(1<<i)==1)Add(ans,dp[j][0]); 
        }
        return ans; 
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值