디지털 계산
문제 해결 아이디어
함께 \ (DP [I] [J ] [K] \) 길이를 나타 내기 \ (I는 \) 와 함께 \ (J \) 의 시작 부분에있는 숫자 \ (K \) 발생 참조.
이송 식이다 : - (\. [T] [K] \ [K] + = \ sum_ ^ {T} = {0} (9) DP [. 1 I]가 DP [I] [J]) 즉, 개수 각 (A)의 전방에 배치 \ (J \) 하지만,이 앞에 \ (J \) 우리의 계산으로하지 못하고, 그 것이다 : \ (DP [I] [J] [J] + = {I-10 ^ 1. } \) . 이 때 그주의는 공의를 선두로 계산된다.
그런 다음 (설명하는 방법을 모르겠어요, 사실) 코드를 참조하십시오.
다음 코드는
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
inline ll fpow(ll x, ll p){
ll ans = 1;
for(; p; p >>= 1, x = 1LL * x * x)if(p & 1)ans = 1LL * x * ans;
return ans;
}
ll dp[20][15][15];
void work(ll x, ll ans[])
{
ll num[15];
ll t = x;
int cnt = 0;
while(t){ //把每一位拆出来
num[++cnt] = t % 10;
t /= 10;
}
for(int i = 1; i < cnt; i ++) //小于cnt的位数全加上
for(int j = 1; j <= 9; j ++)
for(int k = 0; k <= 9; k ++)
ans[k] += dp[i][j][k];
for(int j = 1; j < num[cnt]; j ++) //相同位数小于最高位的全加上
for(int k = 0; k <= 9; k ++)
ans[k] += dp[cnt][j][k];
for(int i = cnt - 1; i >= 1; i --){ //遍历每一位
for(int j = 0; j < num[i]; j ++) //小于这位上数字的全加上
for(int k = 0; k <= 9; k ++)
ans[k] += dp[i][j][k];
for(int u = cnt; u > i; u --) //前面这几位都相等,出现了相同的次数
ans[num[u]] += num[i] * fpow(10LL, i - 1);
}
}
int main()
{
ll a, b;
scanf("%lld%lld", &a, &b);
for(int i = 1; i <= 12; i ++){
for(int j = 0; j <= 9; j ++){
for(int k = 0; k <= 9; k ++)
for(int t = 0; t <= 9; t ++)
dp[i][j][k] += dp[i - 1][t][k];
dp[i][j][j] += fpow(10LL, i - 1);
}
}
ll ans1[15] = {0};
ll ans2[15] = {0};
work(b + 1, ans1);
work(a, ans2);
for(int i = 0; i <= 9; i ++)
printf("%lld ", ans1[i] - ans2[i]);
return 0;
}