题意:
定义一个具有2n位的正整数,其前n位之和与后n位之和相等,则为lucky数。给定一个区间l,r,问有多少个正数可以通过修改某一位数从而变成lucky数?不能含前导0。
tip:
定义dp[i][j][p][q]表示前I位和为j其中数位上最大值是p 最小值是q的方案数。。
我们先把整个区间分开,10,99],[1000,9999],[100000,999999]。。。
然后如果[1,K]完全包含了某个区间,就直接统计把答案统计进去就行了。我们假设k将某个区间给分开了,也就是说k在上面的四个区间中的一个中,那么我们就需要单独考虑一下这个区间怎么做。
如果K的位数是奇数直接统计包含了几个区间就行了,因为奇数位是不可能分割以上区间的。
那么如果是偶数位,求这个小区间中有多少个近似幸运。
在分开这个小区间,例如这个数为2313分为:[1***],[20**],[21**],[22**],[230*],[2310],[2311][2312]一共有多少个符合题意的数字,于是将区间一分为二,如果长度是2n,dp0表示前n个dp1表示后n个。因为不能有前导零,所以dp0的第一位不能是0 初始化的是第一位开始,dp1可以有签到零,所以初始化从0开始。两个dp过程一样:枚举ijpq如果遇到现在是*,那么要填的数从1~9枚举,p,q跟着变,check的时候,枚举dp0[n]…dp1[n]…的sum p,q..首先如果sum相同肯定不行(改一个之后一定不相同),其次,检验
改变后最小值:sum-q(一边的最大值)+0
改变后最大值:sum-p(一边的最小值)+9
是否在另一个sum中间,注意如果是dp0,第一位也可以改,但p,q没记录它,单独用s[0]和p q比较一下。最后答案相加
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
LL l,r,n;
int num[20],a[20];
LL dp0[10][10*9][10][10],F[20];///前i位和为j 最小为p 最大是q 的方案数
LL dp1[10][10*9][10][10];
void _dp0(string s){
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j <= 9*n ; j++){
for(int p = 0 ; p <= 9 ; p++){
for(int q = 0 ; q <= 9 ; q++){
dp0[i][j][p][q] = 0;
}
}
}
}
if(s[1]=='*'){
for(int i = 0;i <= 9;i++) dp0[1][s[0]-'0'+i][i][i] = 1;
}
else
dp0[1][s[0]-'0'+s[1]-'0'][s[1]-'0'][s[1]-'0'] = 1;
int mk = 1;
for(int i = mk ; i < n ; i++){
for(int j = 0 ; j <= 9*n ; j++){
for(int p = 0 ; p <= 9 ; p++){
for(int q = 0 ; q <= 9 ; q++){
if(dp0[i][j][p][q] > 0){
if(s[i+1] == '*'){
for(int k = 0 ; k <= 9 ; k ++){
dp0[i+1][j+k][min(p,k)][max(q,k)] += dp0[i][j][p][q];
}
}
else{
int tmp = s[i+1]-'0';
dp0[i+1][j+tmp][min(p,tmp)][max(q,tmp)] += dp0[i][j][p][q];
}
}
}
}
}
}
}
void _dp1(string s){
for(int i = 0 ; i < n ; i++){
for(int j = 0 ; j <= 9*n ; j++){
for(int p = 0 ; p <= 9 ; p++){
for(int q = 0 ; q <= 9 ; q++){
dp1[i][j][p][q] = 0;
}
}
}
}
if(s[0]=='*'){
for(int i = 0;i <= 9; i++) dp1[0][i][i][i] = 1;
//cout <<"a a"<<endl;
}
else{
dp1[0][s[0]-'0'][s[0]-'0'][s[0]-'0'] = 1;
//cout <<"aaaaaaaa"<<endl;
}
int mk = 0;
//cout <<"n = "<<n<<endl;
for(int i = mk ; i < n-1 ; i++){
for(int j = 0 ; j <= 9*n ; j++){
for(int p = 0 ; p <= 9 ; p++){///最小
for(int q = 0 ; q <= 9 ; q++){///最大
if(dp1[i][j][p][q] == 0) continue;
//cout <<" ss "<<endl;
if(s[i+1] == '*'){
for(int k = 0 ; k <= 9 ; k ++){
dp1[i+1][j+k][min(p,k)][max(q,k)] += dp1[i][j][p][q];
}
}
else{
int tmp = s[i+1]-'0';
dp1[i+1][j+tmp][min(p,tmp)][max(q,tmp)] += dp1[i][j][p][q];
}
}
}
}
}
}
LL check(string s){
//cout <<s<<endl;
if(s.size() == 2){
if(s[1] == '*') return 9;
else{
if(s[0] == s[1]) return 0;
return 1;
}
}
string s0 = "",s1 = "";
n = s.size()/2;
for(int i = 0 ; i < n ; i++) s0.push_back(s[i]);
for(int i = 0 ; i < n ; i++) s1.push_back(s[i+n]);
_dp0(s0);
_dp1(s1);
LL ans = 0;
for(int sum0 = 0 ; sum0 <= 9*n ; sum0++){
for(int p0 = 0 ; p0 <= 9 ; p0++){
for(int q0 = 0 ; q0 <= 9 ; q0++){
if(dp0[n-1][sum0][p0][q0] == 0) continue;
for(int sum1 = 0 ; sum1 <= 9*n ;sum1++){
if(sum1 == sum0) continue;
//cout <<"sum1 = "<<sum1<<endl;
for(int p1 = 0 ; p1 <= 9 ; p1 ++){
for(int q1 = 0 ;q1 <= 9 ; q1++){
if(dp1[n-1][sum1][p1][q1] == 0 ) continue;///min: -max+0 max: -min+9
//cout <<"bb = "<<endl;
if( ((min(sum0-q0+0,sum0+1-(s[0]-'0')) <= sum1) && (max(sum0+9-p0,sum0+9-(s[0]-'0')) >= sum1) )||
(( sum1-q1+0 <= sum0) && ( sum1+9-p1 >= sum0) )){
//cout <<"hah"<<endl;
ans += dp0[n-1][sum0][p0][q0]*dp1[n-1][sum1][p1][q1];
}
}
}
}
}
}
}
//cout <<"ans - > "<<ans<<endl;
return ans;
}
LL getnum(int cnt){
string s0 = "",s1 = "";
LL ans= 0;
for(int t = cnt ; t >= 1; t--){
int d = num[t];
for(int i = (t == cnt?1:0) ; i < d ; i++){
s1 = s0;
s1.push_back('0'+i);
for(int j = t-1;j >= 1;j--) s1.push_back('*');
ans += check(s1);
}
s0.push_back('0'+d);
}
return ans;
}
LL sov(int k){
if(k < 10) return 0;
int cnt = 0,tmp = k;
LL ans = 0;
memset(num,0,sizeof(num));
while(tmp > 0){
num[++cnt] = tmp%10;
tmp /= 10;
}
for(int i = 2 ; i < cnt ;i+=2)
ans += F[i];
if((cnt&1) || k == 0){
return ans;
}
ans += getnum(cnt);
return ans;
}
int main(){
F[2]=81;F[4]=7389;F[6]=676133;F[8]=62563644;
while(cin >> l >>r)
cout <<sov(r+1)-sov(l)<<endl;
}
//1200 1210