[SCOI2009]windy數
阿新 • • 發佈:2018-07-09
-a code its 滿足 font style ini bre amp
題目:BZOJ1026、洛谷P2657。
題目大意:
給你\(A,B\),求\([A,B]\)中滿足:沒有前導0且相鄰兩位的數字相差至少為2的整數 的個數。
解題思路:
數位DP。
設\(DP{i,j}\)表示\(i\)位,最高位為\(j\)\((j可以為0)\)並滿足條件的個數。
則\(DP{i,j}=\sum\limits_{k=0}^9 DP_{i-1,k}\times [|j-k|>1]\)
邊界:\(DP_{1,x}=1\)。
然後分別計算\(1~A-1\)和\(1~B\)中滿足條件的個數,相減即可。(BZOJ不資瓷C++11差評)
C++ Code:
#include<cstdio> typedef int I; I a,b,dp[15][15],dd[15]; inline I abs(const I a){return a<0?-a:a;} void init(){ for(I i=9;~i;--i)dp[1][i]=1; for(I i=1;10/++i;){ for(I j=9;~j;--j) for(I k=9;~k;--k) if(abs(j-k)>1)dp[i][j]+=dp[i-1][k]; } } inline I calc(I x){ I len=0,ans=0; for(;x;x/=10)dd[++len]=x%10; for(I i=len;--i;) for(I j=9;j;--j)ans+=dp[i][j]; for(I i=1;dd[len]>i;++i)ans+=dp[len][i]; for(I i=len;--i;){ for(I j=0;j<dd[i];++j) if(abs(dd[i+1]-j)>1)ans+=dp[i][j]; if(abs(dd[i+1]-dd[i])<2)break; } return ans; } I main(){scanf("%d%d",&a,&b);init();return!printf("%d\n",calc(b+1)-calc(a));}
[SCOI2009]windy數