您的位置:首页 > 其它

【BZOJ】1026 [SCOI2009]windy数 数位dp

2017-05-31 19:22 573 查看
题目传送门

感觉自己真的是越来越菜了,连数位dp都写不来了……

定义f[i][j]表示当前取到第i位(从高位到低位),当前位置为j的方案数。

然后就是对于是否存在前导0的分类讨论,并同时统计答案。

最后利用差分的思想,把[l,r]的windy数的数量转化成[1,r]的windy数的数量减去[1,l-1]的windy数的数量即可。

附上AC代码:

#include <cstdio>
#include <cctype>
using namespace std;

const int n=9;
int a,b,f[11][11],ans1,ans2,dig[11];

inline char nc(){
static char ch[100010],*p1=ch,*p2=ch;
return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;
}

inline void read(int &a){
static char c=nc();int f=1;
for (;!isdigit(c);c=nc()) if (c=='-') f=-1;
for (a=0;isdigit(c);a=a*10+c-'0',c=nc());
a*=f;return;
}

inline int abs(int a){
return a>0?a:-a;
}

inline int count(int x){
if (!x) return 0;
int len=0,sum=0;
while (x) dig[++len]=x%10,x/=10;
for (int i=len; i; --i){
if (len-i>=2&&abs(dig[i+1]-dig[i+2])<2) break;
for (int j=0+(i==len); j<dig[i]+(i==1); ++j)
if (i==len||abs(j-dig[i+1])>=2) sum+=f[i][j];
}
for (int i=len-1; i; --i)
for (int j=1; j<=n; ++j)
sum+=f[i][j];
return sum;
}

int main(void){
read(a),read(b);
for (int i=0; i<=n; ++i) f[1][i]=1;
for (int i=2; i<=10; ++i)
for (int j=0; j<=n; ++j)
for (int k=0; k<=n; ++k)
if (abs(j-k)>=2) f[i][j]+=f[i-1][k];
printf("%d",count(b)-count(a-1));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: