Luogu P2657 [SCOI2009]windy数

Posted cjoiershiina-mashiro

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu P2657 [SCOI2009]windy数相关的知识,希望对你有一定的参考价值。

题目
首先我们可以非常轻松地预处理出(f_{i,j})表示一个最高位为(i)位且该位为(j)的windy数的个数。
然后我们可以利用经典容斥把答案变成求([1,x])的windy数个数。
(x)(len)位,从低到高位分别是(a_1,cdots,a_{len})
首先我们把位数小于(len)的答案求出。
然后求出位数等于(len)且首位小于(a_{len})的答案。
然后我们从大到小枚举(lensim i-1)位相等,(i)位不等,枚举第(i)位从(1)(a_{i}-1),如果第(i)位的数(j)(a_{i+1})差的绝对值(ge2),那么这里的答案就是(f_{i,j})

#include<bits/stdc++.h>
using namespace std;
int f[11][11],a[11];
int abs(int a){return a<0? -a:a;}
void init()
{
    for(int i=0;i<=9;++i) f[1][i]=1;
    for(int i=2,j,k;i<=10;++i) for(j=0;j<=9;++j) for(k=0;k<=9;++k) if(abs(j-k)>=2) f[i][j]+=f[i-1][k];
}
int cal(int x)
{
    int i,j,len=0,ans=0;
    while(x) a[++len]=x%10,x/=10;
    for(i=1;i<len;++i) for(j=1;j<=9;++j) ans+=f[i][j];
    for(i=1;i<a[len];++i) ans+=f[len][i];
    for(i=len-1;i;--i)
    {
    for(j=0;j<a[i];++j) if(abs(j-a[i+1])>=2) ans+=f[i][j];
    if(abs(a[i+1]-a[i])<2) break;
    }
    return ans;
}
int main(){int a,b;init();cin>>a>>b;cout<<cal(b+1)-cal(a);}

以上是关于Luogu P2657 [SCOI2009]windy数的主要内容,如果未能解决你的问题,请参考以下文章

luogu P2657 [SCOI2009]windy数 数位dp入门题

P2657 [SCOI2009]windy数

P2657 [SCOI2009]windy数

luogu2657bzoj1026 [SCOI2009]windy数 [动态规划 数位dp]

P2657 [SCOI2009] windy 数

P2657 [SCOI2009]windy数