[P8766 [蓝桥杯 2021 国 AB] 异或三角]题解-数位DP
P8766 [蓝桥杯 2021 国 AB] 异或三角
分析
题目中给出了三个限制
首先我们不妨设
而由于我们把
所以
1.
2.
3.
而在枚举过程中,我们只需要保证
由2可知:
这样就得到了需要满足的三个条件:
1.
2.
3.
而对于任意一位,满足条件的只有四组
我们就可以只对
可以令
它的每一位分别表示我们所要的限制即可
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int n,T,a[50],len=0;
ll dp[50][10][2];
//当前枚举到第id位,是否满足三个状态flag,c是否达到上限limit
ll dfs(int id,int flag,int limit){
//1.出口
if(id==0) return flag==7;//满足所有条件
if(dp[id][flag][limit]!=-1) return dp[id][flag][limit];
//2.能做的事情
int bound= limit==1 ?a[id]:1;
ll res=0;
for(int i=0;i<=bound;i++){
if(i==0){//c=0 对应 (0,0,0),(1,1,0)
int a=flag&1,b=flag>>1 &1;//判断a<c,b<c
res+=dfs(id-1,flag,limit&&i==bound);//(a,b,c)=(0,0,0)
if(a&&b) res+=dfs(id-1,flag|4,limit&&i==bound); //(a,b,c)=(1,1,0)
}
if(i==1){//c=0 对应 (1,0,1),(0,1,1)
res+=dfs(id-1,flag|2,limit&&i==bound);//(a,b,c)=(1,0,1)满足b<c
res+=dfs(id-1,flag|1,limit&&i==bound);//(a,b,c)=(0,1,1)满足a<c
}
}
return dp[id][flag][limit]=res;
}
ll solve(int x){
len=0;
while(x){
a[++len]=x%2;
x/=2;
}
memset(dp,-1,sizeof(dp));
return dfs(len,0,1);
}
int main(){
/*2023.4.22 hewanying P8766 [蓝桥杯 2021 国 AB] 异或三角 数位dp*/
scanf("%d",&T);
while(T--){
scanf("%d",&n);
printf("%lld\n",solve(n)*3);
}
return 0;
}
总结
1.在我们特定顺序时,一定要注意题目给的是有序对还是无序对,要进行相应的转换
2.定了
3.多种状态可以采用状压来存储
本文作者:H_W_Y
本文链接:https://www.cnblogs.com/H-W-Y/p/17342556.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步