2019 牛客暑假多校 7 H pair (数位dp)

题目连接

今天来复习数位dp,补了这个题我发现是才理解数位dp。。

 

直接统计合法的剪枝的次数比统计不合法的少,那么定义dp[pos][s1][s2][l1][l2]表示不合法的对数,再把zero的状态去掉(也就是x,y不能选0),那么现在统计了x,y为0的不合法的数量;(1)当x = 0,y属于[C,B]时不合法(2)当y = 0,x属于[C,A]时不合法,减去这部分即可

统计(x&y<=c)&&(x^y>=c)即可


dp[pos][s1][s2][l1][l2]表示在pos位置,在l1和l2 的约束条件下,状态为s1,s2的方案数

s1==0    a[pos]&b[pos]==c[pos]

s1==1   a[pos]&b[pos]

 

s2==0    a[pos]^b[pos]==c[pos]

s2==1   a[pos]^b[pos]

 

通过数位dp特殊的叠加递归得到答案。。。

#include
using namespace std;
typedef long long ll;
const int N=32;
int a[N],b[N],c[N];
ll A,B,C;
ll dp[32][2][2][2][2];
ll dfs(int pos,int s1,int s2,int l1,int l2)
{
    if(pos<1) return 1;
    if(dp[pos][s1][s2][l1][l2]!=-1)
        return dp[pos][s1][s2][l1][l2];

    int up1=l1 ? a[pos]:1;
    int up2=l2 ? b[pos]:1;
    ll ans=0;
    for(int i=0;i<=up1;++i)
    {
        for(int j=0;j<=up2;++j)
        {
            if((i&j)>c[pos]&&!s1) continue;
            if((i^j)c[pos]||s2) t2=1;
            ans+=dfs(pos-1,t1,t2,l1&&(i==up1),l2&&(j==up2));
        }
    }
    dp[pos][s1][s2][l1][l2]=ans;
    return ans;
}
int main()
{
    int _;cin>>_;while(_--)
    {
        scanf("%lld%lld%lld",&A,&B,&C);
        for(int i=0;i

 

你可能感兴趣的:(dp---数位DP)