【题解】CF8E Beads

CF8E Beads

确实不会做。。。

显然满足题意的二进制串的首位必须是 0 0 0。考虑一位一位地确定答案串。假设已经确定了答案串的前k位,我们假设第 k + 1 k+1 k+1 位是 0 0 0,则要设法统计出满足条件的串的个数 s s s。 那么如果 s < m s<m s<m,则答案串第 k + 1 k+1 k+1 位为 1 1 1 ,同时 m = m − s m=m−s m=ms ;否则答案串第 k + 1 k+1 k+1 位为 0 0 0。于是问题转化为,统计所有长度为 n n n 的,前缀为 p r e f i x prefix prefix 的二进制串中,满足题目要求的串的个数。 这是一类与数位有关的统计问题,于是很容易想到数位 d p dp dp

那么考虑 d p i , j , r e v , i n v dp_{i,j,rev,inv} dpi,j,rev,inv 表示,当前已经确定了前 i i i 位和末 j j j 位, r e v rev rev 表示前 i i i 位与末 j j j 位的逆序是否相等, i n v inv inv 表示前 i i i 位与末 j j j 位的逆序取反后是否相等。状态转移比较显然,我们枚举第 i + 1 i+1 i+1 位和第 n − i n−i ni 位的取值,如果它满足 p r e f i x prefix prefix 的限制,且新的串没有违反题目要求, 那么更新 r e v rev rev i n v inv inv 的状态,并累加到对应的新状态上。

#include<bits/stdc++.h> using namespace std; long long n,k; long long dp[55][2][2]; int a[55]; long long dfs(int pos,int lim1,int lim2) { if(pos<n-pos+1) return 1; if(dp[pos][lim1][lim2]>=0) return dp[pos][lim1][lim2]; long long tot=0; for(int i=0;i<=1;i++) if(a[pos]==i||a[pos]==-1) { for(int j=0;j<=1;j++) if(a[n-pos+1]==j||a[n-pos+1]==-1) { if(lim1&&i>j||lim2&&i>!j||pos==n-pos+1&&i!=j) continue; tot+=dfs(pos-1,lim1&&(i==j),lim2&&(i==!j)); } } return dp[pos][lim1][lim2]=tot; } int main() { scanf("%lld%lld",&n,&k),k++; memset(a,-1,sizeof(a)),memset(dp,-1,sizeof(dp)),a[n]=0; long long nw=dfs(n,1,1); if(nw<k) { printf("-1"); return 0; } for(int i=n-1;i>=1;i--) { a[i]=0,memset(dp,-1,sizeof(dp)); long long nw=dfs(n,1,1); if(nw<k) { k-=nw,a[i]=1; } } for(int i=n;i>=1;i--) printf("%d",a[i]); }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530359.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(12)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示