[数位DP] Codeforces 809C Round #415 (Div. 1) C. Find a car

题目梗概

有一个 1e91e9 的矩阵,记第x行y列的元素为(x,y)
(x,y)的值,定义为所有(i,y),(x,j)(1≤i

解题思路

这种题目一看就是有一个结论。

通过一些奇怪的途径我知道了结论,位于(x,y)的数字为 ((x1)xor(y1))+1

运用容斥原理我们只需要考虑到(1,1)的矩阵的数字和。

定义 f[i][j][k][t] 表示前i位,x,y,x^y的值是否紧贴给定值。

g[i][j][k][t] 存储方案数。

转移时注意不超过范围。

#include<cstdio>
#include<cstring>
#define LL long long
using namespace std;
const int tt=1000000007;
LL f[35][2][2][2],g[35][2][2][2];
int T,x1,y1,x2,y2,K;
LL work(int x,int y){
    if (x<0||y<0) return 0;
    memset(f,0,sizeof(f));
    memset(g,0,sizeof(g));
    f[32][1][1][1]=1;
    for (int i=32;i>=1;i--)
    for (int j1=0;j1<2;j1++)
    for (int j2=0;j2<2;j2++)
    for (int j3=0;j3<2;j3++) if (f[i][j1][j2][j3])
    for (int a1=0;a1<2;a1++)
    for (int a2=0;a2<2;a2++){
        if (j1&&a1>((x>>i-1)&1)) continue;
        if (j2&&a2>((y>>i-1)&1)) continue;
        if (j3&&(a1^a2)>((K>>i-1)&1)) continue;
        int A=(j1&&a1==((x>>i-1)&1)),B=(j2&&a2==((y>>i-1)&1)),C=(j3&&(a1^a2)==((K>>i-1)&1));
        (f[i-1][A][B][C]+=f[i][j1][j2][j3])%=tt;
        (g[i-1][A][B][C]+=g[i][j1][j2][j3]*2+(a1^a2)*f[i][j1][j2][j3])%=tt;
    }
    LL ans=0;
    for (int j1=0;j1<2;j1++)
    for (int j2=0;j2<2;j2++)
    for (int j3=0;j3<2;j3++)
    (ans+=f[0][j1][j2][j3]+g[0][j1][j2][j3])%=tt;
    return ans;
}
int main(){
    freopen("exam.in","r",stdin);
    freopen("exam.out","w",stdout);
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&K);
        x1--;y1--;x2--;y2--;K--;
        printf("%lld\n",((work(x2,y2)-work(x2,y1-1)-work(x1-1,y2)+work(x1-1,y1-1))%tt+tt)%tt);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值