1. 程式人生 > >BZOJ -1799 self 同類分佈

BZOJ -1799 self 同類分佈

Description

給出a,b,求出[a,b]中各位數字之和能整除原數的數的個數。

Sample Input

10 19

Sample Output

3

HINT

【約束條件】1 ≤ a ≤ b ≤ 10^18

思路:

數位dp,dp[i][j][k]表示第i位,j表示當前餘數,k表示第i位的數字。

for (int i = 1; i <= pos * 9; i++)中的pos * 9是每一位數字的和的最大值。

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;

typedef long long ll;
ll a[20], dp[20][180][180];

ll dfs(int pos, int p, int sta1, int sta2, bool limit)
{
   if (pos == -1) 
   {
       return (sta1 == 0 && sta2 == p);
   }
   if (sta2 > p || sta2 + (pos + 1) * 9 < p)
   {
       return 0;
   }
   if (!limit && dp[pos][sta1][sta2] != -1)
   {
       return dp[pos][sta1][sta2];
   }
   int up = limit ? a[pos] : 9;
   ll result = 0;
   for (int i = 0; i <= up; i++)
   {
       result += dfs(pos - 1, p, (sta1 * 10 + i) % p, sta2 + i, limit && (i == a[pos]));
   }
   if (!limit)
   {
       dp[pos][sta1][sta2] = result;
   }
   
   return result;
}

ll solve(ll x )
{
    int pos = 0;
    ll up = x;
    while (x > 0)
    {
        a[pos] = x % 10;
        x /= 10;
        pos++;
    }
    ll result = 0;
    cout << "pos * 9 = " << pos * 9 << endl;
    for (int i = 1; i <= pos * 9; i++)
    {
        memset(dp, -1, sizeof(dp)); 
        result += dfs(pos - 1, i, 0, 0, 1);
    }
    return result;
}

int main()
{
    ll l, r;
    cin >> l >> r;
    cout << solve(r) - solve(l - 1) << endl;    
    
    return 0;
}