30pts数位dp求助
查看原帖
30pts数位dp求助
399116
LYqwq楼主2024/12/21 10:10
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
int a[12];
int f[12][10][3][3][2];
/* f[i][j][len][tag][lim];
   前i高位,第i位为j,
   len: 末尾连续相同数字个数-1(若前面已出现3个连续,len也为3-1=2)
   tag: 2位二进制数,00表示没有4也没有8,01表示有4无8,10表示有8无4
   lim: 是否顶着上界 */

int solve(ll x){
    if(x<1e10) return 0;
    memset(f,0,sizeof(f));
    for(int i=9; i>=0; i--) a[i]=x%10,x/=10;
    f[0][0][0][0][1]=1;
    // for(int j=0; j<=9; j++)
    //     for(int tag=0; tag<=2; tag++)
    //         f[0][j][0][tag][1]=1;
    for(int i=0; i<=9; i++)
      for(int j=0; j<=9; j++)
        for(int len=0; len<=2; len++)
          for(int tag=0; tag<=2; tag++)
            for(int lim=0; lim<=1; lim++)
              for(int k=0; k<=9; k++){
                int i_=i+1,j_=k,len_,tag_=tag,lim_;
                if(k==j) len_=len+1;
                else len_=0;
                if(len==2) len_=2;
                tag_|=(k==4 ? 1 : (k==8 ? 2 : 0));
                if(tag_==3 || lim && k>a[i_]) continue;
                lim_=lim && k==a[i_];
                f[i_][j_][len_][tag_][lim_]+=f[i][j][len][tag][lim];
              }
    int res=0;
    for(int j=0; j<=9; j++)
        for(int tag=0; tag<=2; tag++)
            for(int lim=0; lim<=1; lim++)
                res+=f[9][j][2][tag][lim];
    return res;
}

int main(){
    ll l,r;
    scanf("%lld%lld",&l,&r);
    printf("%d\n",solve(r)-solve(l-1));
    return 0;
}

https://www.luogu.com.cn/record/195385080

2024/12/21 10:10
加载中...