SGU 258. Almost Lucky Numbers

258. Almost Lucky Numbers

time limit per test: 0.5 sec.
memory limit per test: 65536 KB
input: standard
output: standard



The number is called lucky if it consists of 2N digits and the sum of the first N digits is equal to the sum of the last N digits. The number is called almost lucky, if it is possible to change one of its digits to some other in such a way, that a new number is lucky. Your task is to find the count of almost lucky numbers in the interval from A to B (including A and B). 

The first digit can't be changed to zero because of leading zeroes are not allowed.

Input
The only line of the input file contains two integer numbers A and B (0 <= A <= B <= 10^9).

Output
Output the only number - the requested number of almost lucky numbers.

Sample test(s)

Input
 
 
1 99
Output
 
 
81

Note
All two-digits not lucky numbers are almost lucky.
[submit]


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int M=45;
int dp[12][12][111][11][11];
int bit[22];
int dfs(int pos,int n,int sum,int more,int less,bool limit)
{
    if(pos==-1)
        return sum!=M&&sum+more>=M&&sum-less<=M;
    if(!limit&&dp[pos][n][sum][more][less]>=0)return dp[pos][n][sum][more][less];
    int ans=0;
    int ed=limit?bit[pos]:9;
    int i=pos==n-1?1:0;
    for(;i<=ed;i++)
    {
        int ns=pos>=n/2?sum+i:sum-i;
        int nm=pos>=n/2?max(more,9-i):max(more,i);
        int nl=pos>=n/2?max(less,pos==n-1?i-1:i):max(less,9-i);
        ans+=dfs(pos-1,n,ns,nm,nl,limit&&i==ed);
    }
    if(!limit)dp[pos][n][sum][more][less]=ans;
    return ans;
}
int f(int n)
{
    if(n==-1)return 0;
    int len=0;
    while(n)
    {
        bit[len++]=n%10;
        n/=10;
    }
    int ans=0;
    for(int i=2;i<=len;i+=2)
    {
        ans+=dfs(i-1,i,M,0,0,i==len);
    }
    return ans;
}
int main()
{
    memset(dp,-1,sizeof dp);
    int a,b;
    while(cin>>a>>b)
        cout<<f(b)-f(a-1)<<endl;
}


你可能感兴趣的:(DFS,现场赛,浙江工业大学)