数位 DP

1 数位 dp 的基本思路

有关比较大小的从大到小来做;有关进位的从小到大来做。

字典序可以看成分位。

2023.1.9 省选模拟赛 I A

【题意】
给定 x,y,求

i[0,2kx)j[y,2k)[i&j=0]×[(i+x)&(jy)=0]

x,y2200000,通过二进制方式给出。
【分析】
首先这个 jy 不好处理。应该将其换成 j,得到这样的比较清楚的柿子:

i[0,2kx)j[0,2ky)[i&(j+y)=0]×[(i+x)&j=0]

然后我们考虑有加法的话,记录进位即可。令 dpi,0/1,0/1 表示考虑到第 i 位,i+x,j+y 下一位分别有没有进位。枚举 i,j 的取值即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define f(i, a, b) for(int i = (a); i <= (b); i++)
#define cl(i, n) i.clear(),i.resize(n);
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int inf = 1e9;
void cmax(int &x, int y) {if(x < y) x = y;}
void cmin(int &x, int y) {if(x > y) x = y;}
//调不出来给我对拍!
char x[200010],y[200010];
int dp[200010][2][2];
const int mod=1e9+7;
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(NULL);
    cout.tie(NULL);
    //time_t start = clock();
    //think twice,code once.
    //think once,debug forever.
    int n;cin>>n;
    for(int i=n-1;i>=0;i--){cin>>x[i];x[i]-='0';}
    for(int i=n-1;i>=0;i--){cin>>y[i];y[i]-='0';}
    dp[0][0][0]=1;  //x这一维度向右平移
    f(d,0,n-1){
        f(i,0,1)f(j,0,1){
            //枚举i,j这一位的取值。
        //    if(i==1&&j==1)continue;
            f(k, 0, 1) f(l,0, 1) {
                //枚举上一位有没有往前进位。
                if((i+x[d]+k)&j)continue;
                if((j+y[d]+l)&i)continue;
                dp[d+1][(i+x[d]+k>=2?1:0)][(j+y[d]+l>=2?1:0)]+=dp[d][k][l];
                dp[d+1][(i+x[d]+k>=2?1:0)][(j+y[d]+l>=2?1:0)]%=mod;
            }
        }
    }
    cout<<dp[n][0][0]<<endl;
    //time_t finish = clock();
    //cout << "time used:" << (finish-start) * 1.0 / CLOCKS_PER_SEC <<"s"<< endl;
    return 0;
}

1.1 有下界的数位 dp

定义一个数:是一类有字典序的对象,不定长度

形如:问字典序是给定的某一个数 p 之后 k 位的数是哪一个。

我们能做的一般来说是:字典序 某一个数的有多少个数。

第一次遇到感觉很困难,不知道怎么转化。转化的套路称为“枚举 lcp”,也即钦定前 i 位与给定的数相等,第 i+1大于给定的数,之后的位任意。这一类数集记为 Si。那么对于 i<jxSi,ySj,x>p,y>p,x>y

有的题目查询“字典序 某一个数的有多少个”是在数据结构上做的,需要你的变化量级尽量小一点,这个方法“钦定一个数等于 x”的操作是 O(logdn) 的。

posted @   OIer某罗  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?
点击右上角即可分享
微信分享提示