bzoj1026

1026 windy

  数位dp,首先预处理出数组dp[i][j]表示首位为i的包含首位总位数为j的满足条件的数的个数,sum[i]表示位数为i的所有满足条件的数的个数,work(x)表示[1,x]中满足条件的数的个数,然后按套路dp下即可

 

/**************************************************************

    Problem: 1026

    User: syh0313

    Language: C++

    Result: Accepted

    Time:4 ms

    Memory:1292 kb

****************************************************************/

 

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <string>

using namespace std;

long long xx,yy,sum[20],dp[20][20];

int a[20],topt,c[20];

void init()

{

    for (int i=0;i<=9;i++) dp[i][1]=1;

    for (int j=2;j<=10;j++)

     for (int i=0;i<=9;i++)

     {

        for (int k=0;k<=i-2;k++) dp[i][j]+=dp[k][j-1];

        for (int k=i+2;k<=9;k++) dp[i][j]+=dp[k][j-1];

     }

    for (int j=1;j<=10;j++)

    {

        sum[j]=sum[j-1];

        for (int i=1;i<=9;i++) sum[j]+=dp[i][j];

    }

}

long long dfs(int lc,int num)

{

    long long ss=0;

    if (lc==topt+1) return 1ll;

    for (int i=0;i<=num-2;i++)

    if (i<a[lc]) ss+=dp[i][topt-lc+1];

    else if (i==a[lc]) {ss+=dfs(lc+1,i); return ss;}

    for (int i=num+2;i<=9;i++)

    if (i<a[lc]) ss+=dp[i][topt-lc+1];

    else if (i==a[lc]) {ss+=dfs(lc+1,i); return ss;}

return ss;

}

long long work(int x)

{

    memset(a,0,sizeof 0); memset(c,0,sizeof c); topt=0;

    if (x==0) return 0;

    while (x) {c[++topt]=x%10; x/=10;}

    for (int i=1;i<=topt;i++) a[i]=c[topt-i+1];

    long long now=sum[topt-1];

    for (int i=1;i<a[1];i++) now+=dp[i][topt];

    now+=dfs(2,a[1]);

return now;

}

int main()

{

    init();

    //for (int i=1;i<=10;i++) printf("%lld\n",sum[i]);

    while (~scanf("%lld%lld",&xx,&yy))

    {

        printf("%lld",work(yy)-work(xx-1));

    }

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值