1. 程式人生 > >XMOJ 1519-二分+數位dp

XMOJ 1519-二分+數位dp

/****************************
* author:crazy_石頭
* date:2014/04/26
* time: 8 ms 
* algorithm:數位dp+二分 
* Pro:XMU 1519
***************************/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

#define INF INT_MAX
#define eps 1e-8
#define A system("pause")
#define rep(i,h,n) for(int i=(h);i<=(n);i++)
#define ms(a,b) memset((a),(b),sizeof(a))
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define LL long long
const int maxn=250+5;
const int maxm=30;
LL dp[maxn][maxn],digit[maxn],l,r,s;

inline LL dfs(LL pos,LL pre,LL limit)
{
       if(pos==-1) return pre==s;
       if(!limit&&~dp[pos][pre]) return dp[pos][pre];
       LL ret=0,end=limit?digit[pos]:9;
       for(int i=0;i<=end;i++)
       {
               int new_num=pre+i;
               ret+=dfs(pos-1,new_num,limit&&i==end);
       }
       if(!limit) return dp[pos][pre]=ret;
       return ret;
}

inline LL solve(LL n)
{
      LL len=0;
      while(n)
      {
         digit[len++]=n%10;
         n/=10;
      } 
      return dfs(len-1,0,1);//limit等於1表示後繼狀態未搜完,等於0表示後繼狀態已經搜完了;答案放進dp陣列就行; 
}

inline bool ok(LL L,LL R)
{
       return (solve(R)-solve(L-1))>=1;
}

inline void test(LL L,LL R)
{
      LL ans,L1=L;
      while(L<=R)
      {
          LL mid=(L+R)>>1;
          if(ok(L1,mid)) 
          {
              ans=mid;
              R=mid-1;
          }
          else L=mid+1;
      }
      printf("%lld\n",ans);
}
          
int main()
{
    ms(dp,-1);
    scanf("%lld%lld%lld",&l,&r,&s);
    printf("%lld\n",solve(r)-solve(l-1));
    test(l,r);
    //A;
    return 0;
}