码迷,mamicode.com
首页 > 编程语言 > 详细

Codeforces 1245F. Daniel and Spring Cleaning(容斥原理+数位DP)

时间:2019-11-10 09:21:44      阅读:89      评论:0      收藏:0      [点我收藏+]

标签:原理   names   class   typedef   string   temp   传送门   部分   scan   

传送门

题目大意

给你两个数,\(l,r\)\([l,r]\) 中多少对 \(a+b=a\oplus b\)

思路

看了大佬的题解才知道这里要用到二维容斥。
\(f_{x,y}\)\(a\in [0,x],b\in [0,y]\) 时满足条件的对数
那么根据容斥原理答案就是 \(f_{r,r}-f_{l-1,r}\times 2+f_{l-1,l-1}\)
对于其中每一部分都可以用一次数位DP求出来
因为这里对于统计有影响的因素只有两个数是否被限制
那么状态可以直接设计为 \(dp_{pos,lim1,lim2}\)
代表在 \(pos\)\(a,b\) 是否被限制时的个数。

代码

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
typedef long long LL;
int T,a[70],b[70];
LL f[70][2][2];

LL dfs(int pos,int lim1,int lim2){
    if(pos==-1) return 1;
    if(f[pos][lim1][lim2]!=-1) return f[pos][lim1][lim2];
    LL temp=0;
    int up1=lim1?a[pos]:1,up2=lim2?b[pos]:1;
    for(int i=0;i<=up1;i++)
        for(int j=0;j<=up2;j++){
            if(i==1&&j==1) continue;
            temp+=dfs(pos-1,lim1&&i==a[pos],lim2&&j==b[pos]);
        }
    f[pos][lim1][lim2]=temp;
    return temp;
}

LL solve(int x,int y){
    memset(f,-1,sizeof(f));
    int pos;
    for(pos=0;x||y;pos++,x/=2,y/=2)
        a[pos]=x%2,b[pos]=y%2;
    return dfs(pos-1,1,1);
}

int main(){
    scanf("%d",&T);
    int l,r;
    memset(f,-1,sizeof(f));
    while(T--){
        scanf("%d%d",&l,&r);
        printf("%lld\n",solve(r,r)-2*solve(l-1,r)+solve(l-1,l-1));
    }
    return 0;
}

Codeforces 1245F. Daniel and Spring Cleaning(容斥原理+数位DP)

标签:原理   names   class   typedef   string   temp   传送门   部分   scan   

原文地址:https://www.cnblogs.com/BakaCirno/p/11828726.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!