[codeforces 1373E] Sum of Digits 十位数百位数乃至更高位的进位不可能发生

Educational Codeforces Round 90 (Rated for Div. 2)   参与排名人数12840

[codeforces 1373E]    Sum of Digits  十位数百位数乃至更高位的进位不可能发生

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址http://codeforces.com/contest/1373/problem/E

ProblemLangVerdictTimeMemory
E - Sum of Digits GNU C++17Accepted31 ms3900 KB

题目大意:寻找满足公式的最小x.若找不到,输出-1.

难点:思考了一下,主要涉及进位比较难处理。又想了想,满足条件的x应该有时会比较多,如何找最小?

基本思路:

1.十位数百位数乃至更高位的进位不可能发生,举例如下

x=99,k=3
x+0=99
x+1=100
x+2=101
x+3=102

各位位上数字之和9+9+1+0+0+1+0+1+1+0+2=24,对应的n是24

n=24可以找到比上述x更小的情况
x=18,k=3
x+0=18
x+1=19
x+2=20
x+3=21
各位位上数字之和1+8+1+9+2+0+2+1=24

2.因要找最小的x,可以大致判定x+0,x+1,x+2,......,x+k,这k+1个数,在各个位置上的数字差异很小。

3.因要找最小的x,低位尽可能摆大的数,高位尽可能的摆小的数,考虑到要凑成n,故个位上的数需要枚举(从0枚举到9)。

样例模拟过程如下,以下模拟过程,若阅读有障碍,可结合AC代码进行学习。

42 7

4

x的个位是0
0,0+1=1,0+2=2,0+3=3,0+4=4,0+5=5,0+6=6,0+7=7
个位上数字之和0+1+2+3+4+5+6+7=28
还剩42-28=14
14无法均分为7+1=8份,此种情况排除

x的个位是1
1,1+1=2,1+2=3,1+3=4,1+4=5,1+5=6,1+6=7,1+7=8
个位上数字之和1+2+3+4+5+6+7+8=36
还剩42-36=6
6无法均分为7+1=8份,此种情况排除


x的个位是2
2,2+1=3,2+2=4,2+3=5,2+4=6,2+5=7,2+6=8,2+7=9
个位上数字之和2+3+4+5+6+7+8+9=44
还剩42-44=-2
还剩下-2,此种情况排除

x的个位是3
3,3+1=4,3+2=5,3+3=6,3+4=7,3+5=8,3+6=9,3+7=10(1+0=1)
个位上数字之和3+4+5+6+7+8+9+1=43
还剩42-43=-1
还剩下-1,此种情况排除

x的个位是4
4,4+1=5,4+2=6,4+3=7,4+4=8,4+5=9,4+6=10(1+0=1),4+7=11(1+1=2)
个位上数字之和4+5+6+7+8+9+1+2=42
还剩42-42=0
还剩下0,此种情况,十位上数字均分的是0/(1+7)=0
因涉及个位上的进位,x+k对应的十位数是0+1=1

接下来处理x+k
1*10+2=12,12-1=11(注,-1是扣除4+7=11(1+1=2)对应的1+1=2的十位上的1的影响),此处若不明,可结合AC代码进行研究。
11-7=4此时,算出的即是x=4.

AC代码如下:

#include <cstdio>
#include <algorithm>
#define LL long long
#define INF (LL)1<<63-1
using namespace std;
int p[]={0,1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9};//0,1,2,3,4,5,6,7,8,9,10(1+0=1),11(1+1=2),12(1+2=3),13(1+3=4),14(1+4=5),15(1+5=6),16(1+6=7),17(1+7=8),18(1+8=9)
LL ans;
LL solve(int st,int n,int k){
	int i,sum=0;
	LL ret=0,pow=10;//注意pow=10,从十位开始
	for(i=st;i<=st+k;i++)sum+=p[i];//个位之和,已包含进位,这个技巧妙啊
	n-=sum;//剩下的和值
	if(n<0||n%(k+1))return INF;//n<0表示凑不成n;n%(k+1)!=0表示剩下的数据,无法均分
	n/=(k+1);//平均分为k+1份,每份的数值
	if(st+k>=10)n++;//研究最大的数x+k.n++记录的是十位的进位
	while(n>0){
		int tmp=9;//除个位,最高位外的数据
		if(n<9)tmp=n;//可能的最高位数据
		ret+=tmp*pow;
		pow*=10;
		n-=9;//低位,数据越大越好
	}
	ret+=p[st+k];//补回个位,对应x+k数据
	if(st+k>=10)ret--;//退位,尾巴多了1,故退去
	if(ret>=k)return ret-k;
	else return INF;
}
int main(){
	int t,i,n,k;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&k);
		ans=INF;
		for(i=0;i<=9;i++)//个位上的数值
			ans=min(ans,solve(i,n,k));//,printf("i=%d ans=%lld\n",i,ans);
		if(ans==INF)printf("-1\n");
		else printf("%lld\n",ans);	
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值