蒟蒻来写题解了
这题其实思路上还比较简单,分为以下几个步骤:
1:因为数据只有1-9的数字和加号,当有n个加号时,就会有n+1个数字相加(比如1+1,一个加号,两个数字),所以我们分别计算每种有多少个。
2:如何实现和最小呢,首先我们要保证重新组合后的每一个数字的位数都尽可能一样,其次是每个数字的首位要尽可能小,比如32+45,我们要分解成两个数字相加,先安排两个数字的首位,第一个数字首位我们选2,第二个数字首位选3,再继续安排后面的位,所以就得到了24和35,这样就是最小的了。
3:因为数据肯定很多,所以自己写一个大数加法就好
4:这个方法建议大家自己写写,思考5分钟,debug两小时
以下是代码
#include <bits/stdc++.h> using namespace std; typedef long long ll;//我是啥?我为什么会在这个代码里 char s[10000050], ans[10000050];//s用来存原始数据,ans用于输出 int num[10] = {0};//用于记录原始数据中每个数字的出现次数 char a[10000000];//用于记录每一次用于相加数字,为了空间优化这里只有一个数组,后面会重复使用a数组 char change[600000];//在下面用于交换 void bigadd(char *b)//言简意赅,大数加法 { int t = 0, jin = 0, j;//jin表示进位 if (strlen(b) > strlen(ans)) //为了方便我们把长的先给ans { strcpy(change, b); strcpy(b, ans); strcpy(ans, change); } j = strlen(ans) - 1;//从最后加起,小学老师应该教的很清楚了 int i = strlen(b); while (i--) { t = b[i] + ans[j] - 96 + jin; jin = t / 10; if (t >= 10) t = t % 10; ans[j--] = t + 48;//数字转字符所以+48 } while (jin > 0) { if (j >= 0)//当ans本身位数大于b时,有进位可以直接加在ans上 { t = ans[j] - 47;//相当于t=ans[j]-'0'+1; jin = t / 10;//加完还要判断,否则万一ans的这一位是9咋办? t = t % 10; ans[j--] = t + '0'; } else if (j == -1 && jin > 0)//当ans本身的位数不够存这个和时,就要进位了 { ans[strlen(ans) + 1] = 0; for (int p = strlen(ans); p > 0; p--)//ans数组整体后移 ans[p] = ans[p - 1]; ans[0] = '1';//别问为什么等于1,问就是你加法没学好 jin = 0; } } } int main() { int j = 0; ll sum = 0, k = 0;//sum用来记录加号的个数 gets(s); for (int i = 0; s[i] != 0; i++) { if (s[i] == '+') sum++; else num[s[i] - '0']++; //出现什么数字a则num[a]+1 } for (int i = 1; i < 10; i++) { while (num[i]--) //重组s数组,让s数组升序并且去掉加号,这样可以保证取的时候从小到大 s[k++] = '0' + i; } s[k] = 0;//给s一个结束符 for (int i = 0; i <= sum; i++) { j = 0; for (int p = i; p < k; p += (sum + 1))//这一步很关键!因为一共有sum+1个数字,所以每个数字加一位的话会用掉sum+1个数字,所以每个数字其实就是在s里面取间隔sum+1个位置的数 a[j++] = s[p]; a[j] = 0;//给a一个结束符 bigadd(a); //往ans里面加a } puts(ans); return 0; }