C. Classy Numbers cf edu round50

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[20][10];//从低位到高位第i位数字中非零数字小于等于j的数字个数 
ll cal(ll num)
{
    if(num==0)//这里不特判会出来一堆奇妙的结果 
      return 1;
    vector<ll> vec;
    vec.push_back(0);
    while(num)
    {
        vec.push_back(num%10);
        num/=10;
    }
    int cnt=0;
    ll ans=0;
    for(int i=vec.size()-1;i>1;i--)
    {
        if(vec[i])
        {
            if(cnt<3)
            {
                ans+= ( (vec[i]-1)*dp[i-1][3-cnt-1]+dp[i-1][3-cnt] );
            }
            else if(cnt==3)
            {
                ans += dp[i-1][0];
            }
            cnt++;
        }
    }
    if(cnt<=2)
      ans+=vec[1];
    if(cnt<=3)
      ans++;
    return ans;
}
int main()
{
    int T;
    scanf("%d",&T);
    dp[1][0]=1;
    dp[1][1]=9;
    for(int i=2;i<=18;i++)
    {
        dp[i][0]=1;
        for(int j=1;j<=3;j++)
        {
            dp[i][j]=dp[i-1][j-1]*9+dp[i-1][j];//这里得到的是从低位到高位前i位数字非零数字位j个的时候数字的数量 
        }
    }
    for(int i=1;i<=18;i++)
    {
        for(int j=1;j<=3;j++)
        {
            dp[i][j]+=dp[i][j-1];
        }
    }
    while(T--)
    {
        ll L,R;
        scanf("%lld%lld",&L,&R);
        printf("%lld\n",cal(R)-cal(L-1));
    }
}

猜你喜欢

转载自www.cnblogs.com/lishengkangshidatiancai/p/10202135.html