0
点赞
收藏
分享

微信扫一扫

HYSBZ 1799 self 同类分布——数位dp


题意:给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数。

思路:给出a,b,求出[a,b]中各位数字之和能整除原数的数的个数。1<=a<=b<=1e18.
注意到各位数字之和最大是153.考虑枚举这个东西。那么需要统计的是[0,a-1]和[0,b]内各位数字之和为x且能整除x的数字个数。
那么我们只需要数位dp一波即可。
令dp[pos][i][x]表示有pos位且数字之和为x的数mod P=i的数字个数。

则转移方程显然可得

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int num[20];
ll dp[20][200][200];
ll dfs(int t, int pos, int sum, int mod, bool limit, bool lead) {
if (pos == 0) return (sum==t && mod==0);
if (!limit && !lead && ~dp[pos][sum][mod]) return dp[pos][sum][mod];
int up = limit ? num[pos] : 9;
ll ans = 0;
for (int i = 0; i <= up; i++) {
ans += dfs(t, pos-1, sum + i, (10%t*mod+i)%t, limit && i==num[pos], lead && i==0);
}
if (!limit && !lead) dp[pos][sum][mod] = ans;
return ans;
}
ll solve(ll n) {
if (n < 0) return 0;
int pos = 0;
while (n) {
num[++pos] = n % 10;
n /= 10;
}
ll ans = 0;
for (int i = 1; i <= pos*9; i++) {
memset(dp, -1, sizeof(dp));
ans += dfs(i, pos, 0, 0, true, true);
}
return ans;
}
int main() {
ll x, y;
scanf("%lld%lld", &x, &y);
printf("%lld\n", solve(y) - solve(x-1));
return 0;
}

 

举报

相关推荐

0 条评论