Problem Statement | |||||||||||||
The digits 4 and 7 are lucky digits, and all other digits are unlucky. A third level lucky number is a positive integer that is divisible by at least one lucky digit. John and Brus have written down all the third level lucky numbers between a and b, inclusive, and now they would like to count the number of occurrences of each digit between 0 and 9, inclusive, in the numbers they have written. Return a vector<long long> containing exactly 10 elements, where the i-th element (0-based) is the total number of occurrences of digit i. | |||||||||||||
Definition | |||||||||||||
| |||||||||||||
Limits | |||||||||||||
| |||||||||||||
Constraints | |||||||||||||
- | a will be between 1 and 10^16, inclusive. | ||||||||||||
- | b will be between a and 10^16, inclusive. |
数位dp的题居然也能压轴~~服了。
题意:列出区间[a,b]所有能被4或者7整除的数,统计这些数含有多少个digit s,s:0,1,...,9
example:
a = 1, b = 10
|
tricky: 传统的数位dp一般数统计满足条件的数的个数,但是这个题统计的是满足条件的数中digit 0-9的个数。
一开始,如果不仔细分析到这里就很容易跳进死胡同,其实此题可以很简单的转换到常规数位dp。
换一种问法:区间[a,b]中所有满足条件的数x:
x能被4或者7整除的
x含有k个1
这里就可以枚举 k 和digit 0-9。
然后,设计数位dp的递归函数就比较方便了。
#include<cmath>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
#define FOR(i,a,b) for(int i=a;i<b;i++)
#define FORE(i,a,b) for(int i=a;i<=b;i++)
#define MST(a,b) memset(a,b,sizeof(a))
class TheLuckyNumbersLevelThree{
public:
int cur,n;
int d[17];
int tmpsum;
long long dp[17][17][7][4];
int mod4[17],mod7[17];
TheLuckyNumbersLevelThree(){
mod4[0] = mod7[0] = 1;
FOR(i,1,17) mod4[i] = mod4[i-1]*10%4;
FOR(i,1,17) mod7[i] = mod7[i-1]*10%7;
tmpsum = 0;
}
long long dfs(int i,int c,int u,int v,bool flag) {
if(i==-1){
if(!u || !v) return c;
else return 0;
}
if(!flag && tmpsum && dp[i][c][u][v]!=-1 )
return dp[i][c][u][v];
long long ans = 0;
int lim = (flag?d[i]:9);
FORE(s,0,lim){
tmpsum += s;
ans += dfs(i-1,c+((s==cur) && tmpsum),(u+s*mod7[i])%7,(v+s*mod4[i])%4,flag && (s==lim));
tmpsum -= s;
}
if(!flag && tmpsum) dp[i][c][u][v] = ans;
return ans;
}
vector<long long> find(long long a, long long b){
long long sa,sb,x;
vector<long long> ans;
FOR(i,0,10){
cur = i;
for(x = a-1,n = 0;x;x/=10)
d[n++]=x%10;
MST(dp,-1);
sa = dfs(n-1,0,0,0,1);
for(x = b,n = 0;x;x/=10)
d[n++]=x%10;
MST(dp,-1);
sb = dfs(n-1,0,0,0,1);
ans.push_back(sb-sa);
}
return ans;
}
};