XMOJ 1519-二分+數位dp
阿新 • • 發佈:2019-02-17
/**************************** * 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; }