1409D. Decrease the Sum of Digits(贪心,构造)

D. Decrease the Sum of Digits

e m m , n emm贪心的想,先把数字n从高位到低位的数位预处理出来

( ) , b 然后从高位看到低位(高位能不动就不动的原则),现在考虑如何构造最小的数b

i s u m n ( i ) 设前i位数字和是sumn(前i位指的是高位到低位)

s u m n < s , i 如果sumn<s,最后结果前i位肯定不需要变动

0 , 因为最坏情况后面数位都变成0,向自己进一位

s u m n + 1 s , sumn+1一定小于等于s,满足条件

s u m n > s , , ( ) , 0 一旦sumn>s,这一位一定要变动,但是不能变大(情况更糟),只能一直进位变成0

0 , ( 0 ) 也就是从这一位开始的位数都变成0,并向前进一位(因为后面都是0)

s u m n = = s ? s u m n > s ? 那么如果sumn==s呢?和sumn>s的情况有啥不同吗?

可以说基本没有不同

0 s u m n = = s 只不过是说明后面都变成0自己不动可以满足条件sumn==s

扫描二维码关注公众号,回复: 11606799 查看本文章

, , 0 ( ) 但是由于只能执行加法的原因,自己不进位,后面数字都变成0(是减法)

s u m n > s 所以和sumn>s的情况是一样的

如果后面的数位都等于0自己确实不需要变动,但是这种情况开头特判一下就好了


emm可能讲的比较啰嗦不清楚,一定在评论区提问啊看不懂的话!!

#include <bits/stdc++.h>
using namespace std;
#define int unsigned long long
int a[22],b[22],s;
signed main()
{
	int t,n; cin >> t;
	while( t-- )
	{
		cin >> n >> s;
		int len=0,x=n,sumn=0;
		memset(a,0,sizeof(a));	memset(b,0,sizeof(b));
		while( x )
			a[++len]=x%10,sumn+=a[len],x/=10;//预处理数位和 
		if( sumn==s )
		{
			cout << 0 << endl;
			continue;
		}
		sumn=0;
		for(int i=len;i>=1;i--)//高位到低位看 
		{
			sumn+=a[i];
			if( sumn<s )//暂时不需要变动 
				b[i]=a[i];
			else if( sumn>=s )
			{
				b[i+1]++;//向高位进一位 
				for(int j=i;j>=1;j-- )	b[j]=0;//低位都变成0 
				break;
			}	
		}
		int now=0;
		for(int j=1;j<=len;j++)//提取构造的数字 
		{
			b[j+1]+=b[j]/10;//啥意思?b[j]可能等于10,那么先向前进位吧...这个无关紧要,我是严谨一点 
			b[j]%=10;
		}
		now=b[len+1];
		for(int i=len;i>=1;i--)	now=now*10+b[i];
		cout << now-n << endl;
	}
}

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/108417192