数位DP
数位DP
思路分析:首先可以用前缀和的思想,count(i, j) 表示在1 - i中j出现的次数
则a 到 b数字j出现的次数则为count(b, j) - count(a - 1, j)
那么count函数该怎么写呢?我们假设要求数字x在1 - n中第i位出现的次数
首先假设x在第4位,然后n拆开成每一位可以表示成abcdefg,
那么1 - n中的满足条件的数字可以表示成mmmxnnn
\(1 \leq mmmxnnn \leq abcdefg\)
接下来我们进行分类讨论:
1、mmm < abc
那么mmm可以取值的范围是0 - abc - 1,有abc种
而x右边的部分可以取值的范围是0 - 1000, 也就是10的x - 1位数 - 1次方
但要注意的是如果x = 0,则mmm应该从001开始,因为不能前面全为0
因此总数为(abc - !x) * 1000
2、mmm = abc
此时要再次进行分类讨论:
(1)d == x
此时左边不需要分析,右边可取的范围为0 - efg
总数为efg + 1
(2)d > x
同样只要分析右边,右边可取的范围是0 - 999
总数为10的x位数 - 1次方
每一位同理即可,如果x = 0那么从次高位开始遍历,因为最高位不能为0
代码:
//#pragma comment(linker, "/STACK:10240000000000,10240000000000")
//#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i=(a);i<=(b);++i)
#define per(i,b,a) for (int i=(b);i>=(a);--i)
#define lb lower_bound
#define ub upper_bound
#define pb push_back
#define itt iterator
#define endl '\n'
#define IOS ios::sync_with_stdio(0); cin.tie(0);
#define lowbit(x) x & (-x)
#define clr(x) memset(x, 0, sizeof(x));
#define fi first
#define se second
#define mp make_pair
#define MOD 1000000007
typedef vector<int> vii;
typedef vector<long long> vll;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef set<int> si;
typedef set<ll> sll;
const pii moves[] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
ll ksm(ll a, ll b, ll p) {if (b == 0) return 1; ll ns = ksm(a, b >> 1, p); ns = ns * ns % p; if (b & 1) ns = ns * a % p; return ns;}
const int MAXN = 0x7fffffff;
int get(int l, int r, vector <int> &dig)
{
int res = 0;
for(int i = l; i >= r; i --)
res = res * 10 + dig[i];
return res;
}//取得l-r表示的数字
int pow10(int x)
{
int res = 1;
while(x --)
res *= 10;
return res;
}//10的x次方
int count(int num, int x)
{
vii dig;
while(num)
{
dig.push_back(num % 10);
num /= 10;
}
int n = dig.size();
int res = 0;
for(int i = n - 1 - !x; i >= 0; i --)
{
if(i < n - 1)
{
res += get(n - 1, i + 1, dig) * pow10(i); //位数从0开始所以不用i - 1
if(!x)//如果x是0,那么x左边可取的范围从1开始,否则从0开始,所以x = 0时次数要 - 1
res -= pow10(i);//位数从0开始所以不用i - 1
}
// cout << res << endl;
if(dig[i] == x)
res += get(i - 1, 0, dig) + 1;
else if(dig[i] > x)
res += pow10(i);//位数从0开始所以不用i - 1
}
return res;
}
int main ()
{
//IOS;
int a, b;
while(cin >> a >> b, a || b)
{
if(a > b) swap(a, b);
for(int i = 0; i < 10; i ++)
cout << count(b, i) - count(a - 1, i) << " ";
cout << endl;
}
return 0;
}
/*
*/

浙公网安备 33010602011771号