0
点赞
收藏
分享

微信扫一扫

D. Decrease the Sum of Digits (思维问题+构造)Codeforces Round #667 (Div. 3)

原题链接: ​​http://codeforces.com/contest/1409/problems​​​D. Decrease the Sum of Digits (思维问题+构造)Codeforces Round #667 (Div. 3)_字符串
测试样例

input
5
2 1
1 1
500 4
217871987498122 10
100000000000000001 1
output
8
0
500
2128012501878
899999999999999999

题意: 给你一个整数D. Decrease the Sum of Digits (思维问题+构造)Codeforces Round #667 (Div. 3)_自增_02,你可以进行自增操作,求你最少要进行多少次操作才可以使得D. Decrease the Sum of Digits (思维问题+构造)Codeforces Round #667 (Div. 3)_自增_02的位数之和小于等于给定的D. Decrease the Sum of Digits (思维问题+构造)Codeforces Round #667 (Div. 3)_自增_04

解题思路: 这道题看着吓人,但如果理解了就很好处理了(比赛的时候没做出来),我看很多大佬都是用dp写的,但其实没必要,接下来介绍的方法通俗易懂。OK,我们开始进入正题。我们知道,若想让D. Decrease the Sum of Digits (思维问题+构造)Codeforces Round #667 (Div. 3)_自增_02的第D. Decrease the Sum of Digits (思维问题+构造)Codeforces Round #667 (Div. 3)_思维_06位之后的数都变为0,又因为D. Decrease the Sum of Digits (思维问题+构造)Codeforces Round #667 (Div. 3)_自增_02只能自增,那么我们的方法就是一直让D. Decrease the Sum of Digits (思维问题+构造)Codeforces Round #667 (Div. 3)_思维_08自增使得第D. Decrease the Sum of Digits (思维问题+构造)Codeforces Round #667 (Div. 3)_#define_09位进1,那么我们经过这个操作发现了什么?我们让第D. Decrease the Sum of Digits (思维问题+构造)Codeforces Round #667 (Div. 3)_#define_09位进1,抹掉后面的位数。 我们又知道这个题目要求的是D. Decrease the Sum of Digits (思维问题+构造)Codeforces Round #667 (Div. 3)_自增_02的位数之和要小于等于D. Decrease the Sum of Digits (思维问题+构造)Codeforces Round #667 (Div. 3)_自增_04,那么如果不小于,我们是不是就要利用那个方法来实现?由于进位是从低位到高位,那么我们必然是要寻找一个需要进位的位置来使得位数之和小于等于s,那么我们遍历自然是从高位到低位。(如果高位的都不满足,那么低位的就更不可能)。 Ok,有了这个思想我们自然是可以去构建进位后的值,再用进位后的值减去原来的值即是我们要增加的次数。具体看代码,我贴了详细注释。注:代码中用到了两个函数to_string()和stoll()函数这两个一个是将数值转换为字符串一个是将字符串转换为数值,这两个函数都需要新版c++版本才支持。我用的是c++17标准

AC代码

/*
*
*
*/
#include<bits/stdc++.h> //POJ不支持

#define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
#define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
#define pb push_back
#define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define fi first
#define se second
#define mp make_pair

using namespace std;

const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 1e5;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为自定义代码模板***************************************//

ll n;
int t,s;
string str;
void solve(){
str=to_string(n);//将整型数组转化为字符串获取位数之和。
int cnt=0;//统计位数之和。
int len=str.size();//获取整型数据的长度,ok,我们开始遍历,判断是哪里需要进位使得条件成立。
int pos=-1;//pos记录进位点。
rep(i,0,len-1){
cnt+=(str[i]-'0');
if(str[i]=='9'){
continue;//跳过原因是因为不会将其作为进位点,我如果将后面的补上那么这里自然会进1,故忽略这里。
}
if(cnt<s){
//注意这里是小于,因为我们要留取一个空位来使得进位成功!
pos=i;//这里记录位置。当不满足时,pos记录的自然是进位点。
}
}
//通过这个操作我们已然确定了进位点。
//当然我们这里需要判断一些情况。
if(cnt<=s){
//如果位数之和符合,那么我们必然不用进行任何操作。
cout<<0<<endl;
}
else if(pos==-1){
//那么说明进位点在第一个的前面,那么我们自然要构建下面式子。
str="1";
rep(i,0,len-1){
str+="0";
}
cout<<stoll(str)-n<<endl;//这里stoll函数是将字符串转为为整型数据。
}
else{
//那么这个时候我们是同样的方法,让进位点进1,之后的清0即可。
str[pos]++;//进位,之后的全部抹0.
rep(i,pos+1,len-1)
str[i]='0';
cout<<stoll(str)-n<<endl;
}
}
int main(){
//freopen("in.txt", "r", stdin);//提交的时候要注释掉
IOS;
while(cin>>t){
while(t--){
cin>>n>>s;
solve();
}
}
return 0;
}


举报

相关推荐

0 条评论