BZOJ 1026 [SCOI2009]windy数 数位DP?

来源:互联网 发布:男科网络咨询技巧 编辑:程序博客网 时间:2024/04/28 14:37

题意:链接

方法:数位DP?

解析:数位DP个鬼,明明就是数位递推

首先对于这个数据范围,O(1)能过?

再想想不对,9次方最大也就是9位啊!

所以可以想到一种状态f[i][j]代表长度为i且首位为j的windy数

然后就是乱搞递推了f[i][j]=f[i1][k]abs(kj)>=2

之后就是细节调代码按位处理了

不过我有个问题啊喂

为什么我所有的只有一位的值算的都不对啊?别的位就对?

所以我只好无耻一点了,加特判,询问1~9直接返回自己

先挖个坑。

代码:

#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;int f[15][15];int bit[15];void init(){    for(int i=0;i<=9;i++)f[1][i]=1;    for(int i=2;i<=10;i++)    {        for(int j=0;j<=9;j++)        {            for(int k=0;k<=9;k++)            {                if(abs(j-k)>=2)f[i][j]+=f[i-1][k];            }        }    }}int cal(int x){    if(x<10)return x;    if(!x)return 0;    int s_bit=10,ans=0;    while(bit[s_bit]>x)s_bit--;    for(int i=1;i<s_bit;i++)    {        for(int j=1;j<=9;j++)        {            ans+=f[i][j];        }    }    int aft=x/bit[s_bit];    x%=bit[s_bit];    for(int i=1;i<aft;i++)ans+=f[s_bit][i];    int pre_bit=aft;    for(int i=s_bit-1;i;i--)    {        int bit_now=x/bit[i];        if(i!=1)        {            for(int j=0;j<bit_now;j++)            {                if(abs(pre_bit-j)>=2)ans+=f[i][j];            }        }else        {            for(int j=0;j<=bit_now;j++)            {                if(abs(pre_bit-j)>=2)ans+=f[i][j];            }        }        if(abs(pre_bit-bit_now)<2)break;        pre_bit=bit_now;        x%=bit[i];    }    return ans;}int main(){    int a,b;    scanf("%d%d",&a,&b);    init();    bit[1]=1;    for(int i=2;i<=10;i++)bit[i]=bit[i-1]*10;    cal(1);    printf("%d\n",cal(b)-cal(a-1));}
0 0
原创粉丝点击