SB题。
很容易想到先二话不说把十进制转四进制,然后我们考虑DP:
设\(f_{i}\)表示从高位到低位的第\(i\)位填成目标状态的最小步数/方案数
设\(g_{i}\)表示从高位到低位的第\(i\)位填成目标状态\(+1\)的最小步数/方案数(因为涉及到向下一位退位)
那么我们容易得到以下转移:
\[
f_i\leftarrow f_{i-1}+num_i\\f_i\leftarrow g_{i-1}+4-num_i\\g_i\leftarrow f_{i-1}+num_i+1\\g_i\leftarrow g_{i-1}+3-num_i\\
\]
然后就做完了233
#include<cstdio> #include<cstring> #include<algorithm> #define RI register int #define CI const int& using namespace std; const int N=3005,mod=1e9; struct data { int x,y; inline data(CI X=1e9,CI Y=0) { x=X; y=Y; } friend inline data operator + (const data& A,CI x) { return data(A.x+x,A.y); } }f[N],g[N]; int n,len,a[N],b[N]; char s[N]; inline void upt(data& A,const data& B) { if (A.x==B.x) A.y=(A.y+B.y)%mod; else if (B.x<A.x) A=B; } int main() { RI i,j; for (scanf("%s",s+1),n=strlen(s+1),i=1;i<=n;++i) a[i]=s[n-i+1]-'0'; while (n) { int ret=0; for (i=n;i;--i) ret=(ret*10+a[i])%4; b[++len]=ret; for (i=n;i;--i) a[i-1]+=a[i]%4*10,a[i]/=4; while (!a[n]) --n; } for (reverse(b+1,b+len+1),f[0]=data(0,1),g[0]=data(1,1),i=1;i<=len;++i) upt(f[i],f[i-1]+b[i]),upt(f[i],g[i-1]+(4-b[i])), upt(g[i],f[i-1]+(b[i]+1)),upt(g[i],g[i-1]+(3-b[i])); return printf("%d",f[len].y),0; }
来源:https://www.cnblogs.com/cjjsb/p/12274075.html