Codeforces 1245F. Daniel and Spring Cleaning(容斥原理+数位DP)
Posted BakaC1rno
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 1245F. Daniel and Spring Cleaning(容斥原理+数位DP)相关的知识,希望对你有一定的参考价值。
题目大意
给你两个数,(l,r) 求 ([l,r]) 中多少对 (a+b=aoplus b)。
思路
看了大佬的题解才知道这里要用到二维容斥。
设 (f_{x,y}) 是 (ain [0,x],bin [0,y]) 时满足条件的对数
那么根据容斥原理答案就是 (f_{r,r}-f_{l-1,r} imes 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
",solve(r,r)-2*solve(l-1,r)+solve(l-1,l-1));
}
return 0;
}
以上是关于Codeforces 1245F. Daniel and Spring Cleaning(容斥原理+数位DP)的主要内容,如果未能解决你的问题,请参考以下文章
CF1245F: Daniel and Spring Cleaning
CF1245F Daniel and Spring Cleaning(等会了更新)
CF1245F Daniel and Spring Cleaning(等会了更新)