[51nod1425]减减数
初始给定一个整数n。每次可以对其做一个操作,这个操作是将n减去他其中的某一位。得到新的一个数字n’,然后继续操作,直到他变成0为止。
比如24这个例子,24 → 20 → 18 → 10 → 9 → 0
Input
单组测试数据。
第一行有一个整数n(0 ≤ n ≤ 10^12)
Output
输出一个整数表示使得n变成0最少的操作步数。.
呃...今年学车中学noi摸你赛某场的T3....怎么在51nod上才5级啊(掀桌
十连测那时候抄高分代码才过的...现在终于成功乱(背)搞(诵)出来了...
没见过的数位DP姿势。
结构体f[i][j][k].step、.rest:更高的位数最大值为j,将10^(i-1)-k变成<=0的最少步数step、变后的数字为-rest(1<=k<=9)
g[i].step、.rest:将n的最低i位变成<=0的最少步数step、变后的数字为-rest
然后转移的时候其实就是调若干次f数组,每次把当前位的数字-1。需要特判.rest等于0的情况。具体见代码吧。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<cmath> 7 #include<cstdlib> 8 #include<bitset> 9 //#include<ctime> 10 #define ll long long 11 #define ull unsigned long long 12 #define ui unsigned int 13 #define d double 14 //#define ld long double 15 using namespace std; 16 const int maxn=100233; 17 struct zs{ll step;int rest;}f[23][10][10],g[23]; 18 int s[23],premx[23]; 19 //int ff[233333];ll ten[23]; 20 int i,j,k,n,m; 21 22 int ra,fh;char rx; 23 inline int read(){ 24 rx=getchar(),ra=0,fh=1; 25 while((rx<'0'||rx>'9')&&rx!='-')rx=getchar(); 26 if(rx=='-')fh=-1,rx=getchar(); 27 while(rx>='0'&&rx<='9')ra=ra*10+rx-48,rx=getchar();return ra*fh; 28 } 29 inline int max(int a,int b){return a>b?a:b;} 30 /* 31 inline void vio(){ 32 for(i=1;i<=9;i++)ff[i]=1; 33 for(i=10;i<233333;i++){ 34 int mx=0,j=i; 35 while(j)mx=max(mx,j%10),j/=10; 36 ff[i]=ff[i-mx]+1; 37 // if(i<30)printf("%d %d\n",i,ff[i]); 38 } 39 }*/ 40 int main(){ 41 // vio(); 42 ll n; 43 scanf("%lld",&n);int len=0; 44 if(!n)return puts("0"),0; 45 for(ll x=n;x;x/=10)s[++len]=x%10; 46 for(i=/*ten[0]=*/1;i<=len;i++)premx[i]=max(premx[i-1],s[len-i+1]);//,ten[i]=ten[i-1]*10; 47 48 for(i=0;i<=9;i++)for(j=1;j<10;j++)f[1][i][j]=(zs){1,max(0,i-(10-j))}; 49 g[1]=(zs){1,premx[len]-s[1]}; 50 51 register int digit,nrest;ll nstep;zs tmp; 52 for(i=2;i<=len;i++){ 53 if(i<len){ 54 for(j=0;j<=9;j++)for(k=1;k<10;k++){ 55 for(digit=9,nstep=0,nrest=k;digit>=0;digit--){ 56 tmp=f[i-1][max(j,digit)][nrest], 57 nstep+=tmp.step,nrest=tmp.rest; 58 if(!nrest&&digit)nstep++,nrest=max(j,digit); 59 } 60 f[i][j][k]=(zs){nstep,nrest}; 61 //if(!j)printf("%d %d %d (%lld,%d) ff:%d\n",i,j,k,f[i][j][k].step,f[i][j][k].rest,ff[ten[i]-k]); 62 } 63 } 64 65 nstep=g[i-1].step,nrest=g[i-1].rest; 66 if(!nrest&&s[i])nstep++,nrest=premx[len-i+1]; 67 for(digit=s[i]-1;digit>=0;digit--){ 68 tmp=f[i-1][max(premx[len-i],digit)][nrest], 69 nstep+=tmp.step,nrest=tmp.rest; 70 if(!nrest&&digit)nstep++,nrest=max(premx[len-i],digit); 71 } 72 g[i]=(zs){nstep,nrest}; 73 }//printf("%lld %d\n",g[len].step,ff[n]); 74 printf("%lld\n",g[len].step); 75 }