zoukankan      html  css  js  c++  java
  • $SCOI2009 windy$数 数位$dp$

    (Sol)

    数位(dp)常规套路题.

    (dp[i][j])表示从低位到高位填到第(i)位且第(i)位的数字为(j)的方案数.答案就是(sol(r)-sol(l+1).)这里(dp)的过程十分简单,一般出错的也就是计算小于等于(x)(windy)数,所以这里简述一下这个流程:

    首先是预处理出(x)的位数(ct),(a[i])表示数(x)从低到高第(i)位的数字是多少,然后累计第一种安全态的答案(as+=sum _{i=1}^{ct-1}sum _{j=1}^{9}f[i][j]).

    接着累计第二种安全态的答案,也就是第(ct)位(从低到高)的数小于(a[ct])的,(as+=sum_{j=1}^{a[ct]-1}f[ct][j]).

    最后也就是最容易出错的地方便是统计危险态的答案.假设当前填到第(i)位且(i)(ct)的数字都和(x)一样,那么第(i-1)位上填的数就有两个限制,一是要小于(a[i-1]),还有就是要与(a[i])的差的绝对值要大于等于(2).

    会发现上面的统计有两个漏洞,一是如果数(x)(windy)数,那么会少算一个,这个问题很好解决,判断一下就好.令一个问题是假设当前填到(i),且(abs(a[i]-a[i-1])<=2),那么下一位就不能填(a[i-1]),那么也就不用继续统计危险态的答案了,直接(break)掉.

    (Code)

    Code ```cpp #include #define il inline #define Ri register int #define go(i,a,b) for(Ri i=a;i<=b;++i) #define yes(i,a,b) for(Ri i=a;i>=b;--i) #define e(i,u) for(Ri i=b[u];i;i=a[i].nt) #define mem(a,b) memset(a,b,sizeof(a)) #define ll long long #define db double #define inf 2147483647 using namespace std; il int read() { Ri x=0,y=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();} return x*y; } int f[20][10],a[20]; il void init() { go(i,0,9)f[1][i]=1; go(i,2,10) go(j,0,9) go(k,0,9) if(abs(j-k)>=2)f[i][j]+=f[i-1][k]; } il int sol(Ri x) { if(!x)return 0; Ri qvq=x,ct=0,ret=0;bool fl=1; while(qvq){a[++ct]=qvq%10;qvq/=10;} go(i,1,ct-1) go(j,1,9)ret+=f[i][j]; go(i,1,a[ct]-1)ret+=f[ct][i]; yes(i,ct,2) { go(j,0,a[i-1]-1) { if(abs(j-a[i])>=2)ret+=f[i-1][j]; } if(abs(a[i]-a[i-1])<2){fl=0;break;} } return ret+fl; } int main() { init(); Ri l=read(),r=read(); printf("%d ",(sol(r)-sol(l-1))); return 0; } ```
  • 相关阅读:
    老罗锤子手机发布会,我感到深深地愧疚!
    微价值:专访《甜心爱消除》的个人开发者Lee,日入千元
    [个人开发者赚钱二]从自己最熟悉的方面入手,获取小利
    [个人开发者赚钱一]改变思维,从心开始
    个人开发者赚钱一、改变思维,从心开始
    OC中的点语法,成员变量的作用域
    OC self super isa指针
    OC面向对象多态笔记
    OC面向对象继承关系和组合关系笔记
    OC面向对象封装
  • 原文地址:https://www.cnblogs.com/forward777/p/11592770.html
Copyright © 2011-2022 走看看