sgx和路飞
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 128000/64000 KB (Java/Others)
Problem Description
众所周知,sgx是个海贼迷。每个礼拜更新的海贼王他都不会放过。这天晚上,他码完代码结果迷迷糊糊困得睡着了。梦中,他见到了偶像路飞。路飞碰巧没吃东西,想要去sgx家吃东西。大家都知道,路飞是个大胃王。让他敞开吃的话sgx家就被吃穷了。但是又不能不让他吃。所以sgx就出了个题目给他:
在所有自然数集合中,给出区间[A,B],求在此区间内各位数字之和为S的最小数。
你们都是热心的海贼迷,可不能看着路飞饿肚子,而路飞又不懂代码,所以这个艰巨的任务就交给你们完成了。
Input
输入包含三个整数A, B, S (1 ≤ A ≤ B <= 10^18, 1 ≤ S ≤ 162).
Output
满足上述条件的最小元素数值。数据保证答案一定存在。
Sample Input
1 100 10
Sample Output
19
Hint
在1到100之间满足各位数字之和相加等于10的数字最小是19.
#include <stdio.h>
#include <string.h>
const long long INF=1000000000000000000LL;
long long dp[20][200],l,r,mid,ans;
int num[20],len;
long long a,b;
int s;
inline long long dfs(int i,int sum,bool e){
if(i==-1) return sum==s;
if(!e && dp[i][sum]!=-1) return dp[i][sum];
long long ans=0;
int v=(e?num[i]:9);
for(int j=0;j<=v;j++){
ans+=dfs(i-1,sum+j,e&&(j==v));
}
if(!e) dp[i][sum]=ans;
return ans;
}
inline long long solve(long long a){
len=0;
while(a){
num[len++]=a%10;
a/=10;
}
return dfs(len-1,0,1);
}
int main(){
while(~scanf("%lld%lld%d",&a,&b,&s)){
memset(dp,-1,sizeof dp);
l=a,r=b;
int cnt=0;
while(cnt<=64){
mid=l+(r-l)/2;
long long sum=solve(mid)-solve(l-1);
if(sum==0) l=mid+1;
else r=mid-1;
cnt++;
}
printf("%lld\n",l);
}
return 0;
}