hdu5803

来源:互联网 发布:sql去掉重复的数据 编辑:程序博客网 时间:2024/06/14 06:11

题意:
给出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 longusing 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
原创粉丝点击