1009 数字1的数量 数位dp

1级算法题就这样了,前途渺茫啊。。。

给我们一个数字n,求从1到n中所有数字里1的数量;这里给的分类是数位dp,那我们先用dp[i][j]来表示从1到第i位为j的数字1的数量,

例如dp[3][2]就表示从1到299的数字1的数量,那怎么推呢?

假设现在是dp[3][1],也就是从1到199,这个数字更特殊一点点,那么我们可以把它表示为两个部分,1到99和100到199,

现在1到99很简单,就是dp[2][9]就是了,那100到199呢?其实我们可以把它的百位数分离,因为它的百位一定是1,

那么就一定有10^2个1,那就变成了10^2+(1到99之间数字1的数量)。

再来一个例子dp[3][2],现在是1到299了,我们可以把它变成(1到199)+(200到299),1到199就是dp[3][1],

而200到299,因为2不是1,那么200到299等价于1到99.

于是我们可以得出一个大致的结论:

dp[3][1]=  dp[3][0]  +  dp[2][9]  +(1==1)*pow(10,3-1);

dp[3][2]=  dp[3][1]  +  dp[2][9]  +(2==1)*pow(10,3-1);

dp[i][j]=  dp[i][j-1]  +  dp[i-1][9]  +(i==1)*pow(10,i-1);

但是j==0时,j-1等于0,那么我们可以改进一下:

  if(j==0)

  dp[i][j]=dp[i-1][9];  dp[3][0]等价于dp[2][9]

  else

  dp[i][j]=dp[i][j-1]+dp[i-1][9]+(i==1)*pow(10,i-1);

终于把这个东西推完了,但是我们怎么表示一个任意的n呢?

比如说n=435,好,现在我们要求1到435之间的1的数量,435可以分为,(1到399)+(400到435)。

而400到435又可以把4分离,如果4==1(额,我是说如果这个百位上的数字为1),好吧这不可能,那就是(1到399)+(1到35)了,然后35又持续这个过程。。。,但是当n=135时,就是(1到99)+(1到35)+(35+1),最后这个(35+1)是因为百位为1,那么就要加上百位上的1,即(100到135)百位上的1有(35+1)个。直接看代码,我表达不行。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define ll long long
ll dp[15][15],ss[15],n,m;
int main()
{
    cin>>n;
    memset(dp,0,sizeof(dp));
    for(int i=1;i<=9;i++)
    dp[1][i]=1;
    for(int i=2;i<=10;i++)
    {
        for(int j=0;j<=9;j++)
        {
            if(j==0)
            dp[i][j]=dp[i-1][9];
            else
            dp[i][j]=dp[i][j-1]+dp[i-1][9]+pow((j==1)*10,i-1);//先推出 
        }
    }
    int digit[15];
    int len=0;
    ll m=n;
    while(n)
    {
        digit[++len]=n%10;//把每一位上的数字存下来 
        n/=10;
    }
    for(int i=len;i>=1;i--)
    {
        ll s=pow(10,i-1);//例如1435,把435,35 ,5都存下来 
        ss[i]=m%s;
    }
    ll ans=0;
    for(int i=len;i>=1;i--)
    {
        if(i>1) 
        ans+=dp[i][digit[i]-1];
        else
        ans+=dp[i][digit[i]];
        if(digit[i]==1&&i>1)//判断这一位是不是1, 
        {
            ans+=ss[i]+1;
        }
    }
    cout<<ans<<endl;
    return 0;
 } 

猜你喜欢

转载自www.cnblogs.com/6262369sss/p/9282793.html