hdu5803

题意:
给出A、B、C、D。问有多少(a,b,c,d),满足:
a+c>b+d && a+d≥b+c && 0≤a≤A && 0≤b≤B && 0≤c≤C && 0≤d≤D
T≤1000
0≤A,B,C,D≤10^18

#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<iostream>
#define N 100
#define mmod 1000000007
#define LL long long
using namespace std;
int f[N][2][2][2][2][4][4];
int a[N],b[N],c[N],d[N],al,bl,cl,dl,n,ans;
void upd(int &x,int y)
{
    x=(x+y)%mmod;
}
int make(int s,int d)
{
    if(s==2) return 2;
    if(s==3)
    {
        if(d==2) return 0;
        if(d==1) return 3;
        return -1;
    }
    if(s==1)
    {
        if(d==-2) return 0;
        if(d==-1) return 1;
        return 2;
    }
    if(d==-2) return -1;
    if(d==-1) return 3;
    return d;
}
void dp()
{
    for(int i=0;i<=n;i++)
        for(int o1=0;o1<=1;o1++)
            for(int o2=0;o2<=1;o2++)
                for(int o3=0;o3<=1;o3++)
                    for(int o4=0;o4<=1;o4++)
                        for(int s1=0;s1<=3;s1++)
                            for(int s2=0;s2<=3;s2++)
                                f[i][o1][o2][o3][o4][s1][s2]=0;
    f[0][0][0][0][0][0][0]=1;
    for(int i=0;i<n;i++)
        for(int o1=0;o1<=1;o1++)
            for(int o2=0;o2<=1;o2++)
                for(int o3=0;o3<=1;o3++)
                    for(int o4=0;o4<=1;o4++)
                        for(int s1=0;s1<=3;s1++)
                            for(int s2=0;s2<=3;s2++)
                            {
                                if(f[i][o1][o2][o3][o4][s1][s2]==0) continue;
                                for(int d1=0;d1<=1;d1++)
                                {
                                    int t1=o1;
                                    if(o1==0 && d1>a[i+1]) continue;
                                    if(d1<a[i+1]) t1=1;
                                    for(int d2=0;d2<=1;d2++)
                                    {
                                        int t2=o2;
                                        if(o2==0 && d2>b[i+1]) continue;
                                        if(d2<b[i+1]) t2=1;
                                        for(int d3=0;d3<=1;d3++)
                                        {
                                            int t3=o3;
                                            if(o3==0 && d3>c[i+1]) continue;
                                            if(d3<c[i+1]) t3=1;
                                            for(int d4=0;d4<=1;d4++)
                                            {
                                                int t4=o4;
                                                if(o4==0 && d4>d[i+1]) continue;
                                                if(d4<d[i+1]) t4=1;
                                                int h1,h2;
                                                h1=make(s1,d1+d3-d2-d4);
                                                h2=make(s2,d1+d4-d2-d3);
                                                if(h1==-1 || h2==-1) continue;
                                                upd(f[i+1][t1][t2][t3][t4][h1][h2],f[i][o1][o2][o3][o4][s1][s2]);
                                            }
                                        }
                                    }
                                }
                            }
}
int main()
{
    int z;scanf("%d",&z);
    while(z--)
    {
        n=al=bl=cl=dl=0;
        LL t;scanf("%lld",&t);
        while(t) {a[++al]=t%2;t/=2;}
        for(int i=1;i<=al/2;i++) swap(a[i],a[al-i+1]);
        n=max(n,al);

        scanf("%lld",&t);
        while(t) {b[++bl]=t%2;t/=2;}
        for(int i=1;i<=bl/2;i++) swap(b[i],b[bl-i+1]);
        n=max(n,bl);

        scanf("%lld",&t);
        while(t) {c[++cl]=t%2;t/=2;}
        for(int i=1;i<=cl/2;i++) swap(c[i],c[cl-i+1]);
        n=max(n,cl);

        scanf("%lld",&t);
        while(t) {d[++dl]=t%2;t/=2;}
        for(int i=1;i<=dl/2;i++) swap(d[i],d[dl-i+1]);
        n=max(n,dl);

        for(int i=al;i>=1;i--) a[i+n-al]=a[i];
        for(int i=1;i<=n-al;i++) a[i]=0;

        for(int i=bl;i>=1;i--) b[i+n-bl]=b[i];
        for(int i=1;i<=n-bl;i++) b[i]=0;

        for(int i=cl;i>=1;i--) c[i+n-cl]=c[i];
        for(int i=1;i<=n-cl;i++) c[i]=0;

        for(int i=dl;i>=1;i--) d[i+n-dl]=d[i];
        for(int i=1;i<=n-dl;i++) d[i]=0;

        dp();
        ans=0;
        for(int a=0;a<=1;a++)
            for(int b=0;b<=1;b++)
                for(int c=0;c<=1;c++)
                    for(int d=0;d<=1;d++)
                        for(int o1=1;o1<=2;o1++)
                            for(int o2=0;o2<=2;o2++)
                                upd(ans,f[n][a][b][c][d][o1][o2]);
        printf("%d\n",ans);
    }
    return 0;
}

题解:
一开始觉得是分类讨论,化柿子化得有点想吐。。然后看了题解,说可以数位dp,那就dp吧。。
注意10^4枚举每位太慢,转成二进制后就是2^4的了

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值