背景
本题收藏于某OJ题库的高精度算法题单,解法参考SSL_wj 的题解,稍有改进。
原题
1745: 天使的起誓(yubikili)
题目描述
TENSHI非常幸运的被选为掌管智慧之匙的天使。在正式任职之前,她必须和其他新当选的天使一样,要宣誓。宣誓仪式是每位天使各自表述自己的使 命,她们的发言稿被放在N个呈圆形排列的宝盒中。这些宝盒按顺时针方向被编上号码1、2、3……、N-1、N。一开始天使们站在编号为N的宝盒旁。她们各 自手上都有一个数字,代表她们自己的发言稿所在的盒子是从1号盒子开始按顺时针方向的第几个。例如:有7个盒子,那么如果TENSHI手上的数字为9,那 么她的发言稿所在盒子就是第2个。现在天使们开始按照自己手上的数字来找发言稿,先找到的就可以先发言。TENSHI一下子就找到了,于是她最先上台宣 誓:“我将带领大家开启NOI之门……”TENSHI宣誓结束以后,陆续有天使上台宣誓。可以有一位天使找了好久都找不到她的发言稿,原来她手上的数字M 非常大,她转了好久都找不到她想找的宝盒。 任务:请帮助这位天使找到她想找的宝盒的编号。
输入格式
输入文件有一行分别正整数N和M,其中N、M满足
2 ≤ N ≤ 10E8,2 ≤ M ≤ 10E1000
输出格式
只有一行即宝盒的编号。
样例输入
7 9
样例输出
2
思路
这道题就是高精除以高精的一道高精度典型例题(M的范围太大了,都有1000位了,用低精度的除法肯定不行),即疯狂进行高精度减法,直到不能减为止,详细参见本文(这篇文章还没写好,写好了链接上)。
但是但是!!!有一个非常重要的问题,TLE(Time Limit Exceed)!!!因为位数太多,普通除肯定会超时,所以引入移位补零的思想。
移位具体
因为本题方法是高精求余,所以可以先用乘整十、整百、整千……的得数来减 (详细见下文的例子),此时余下的数据规模就会减小很多,再减法求余,便省去大量时间成本。
例如:15000÷600,先转化成 15000-6000×2 -> 15000-12000 = 30000,再不断地用3000减去600,得出结果200。(是不是简单了许多)
AC Code
#include <iostream>
#include <string>
using namespace std;
const int MAX = 1010; //常量定义数组大小
int a[MAX], b[MAX], c[MAX];
string str1, str2;
void jian() { //高精度减法模板
for (int i = MAX - 1; i > 0; i--) {
if (a[i] < b[i]) a[i - 1]--, a[i] += 10;
a[i] -= b[i];
}
}
bool com(int *a, int *b) { //大小比较,判断数组a还能不能继续减,不能返回0
int i = 0;
while (a[i] == b[i] && i < MAX) i++;
if (i == MAX) return true;
else return a[i] >= b[i];
}
void print() { //去除前导0并输出
int i = 1;
while (a[i] == 0 && i < MAX) i++;
if (i == MAX) cout << str1;
else for (int j = i; j < MAX; j++) cout << a[j];
}
void chu() { //★灵魂@_@ 高精除+移位处理 (不然TLE)
int j = 1;
while (com(a, b)) {
j++;
for (int i = 2; i < MAX; i++) {
b[i - 1] = b[i];
b[i] = 0;
}
}
while (j > 0) {
while (com(a, b)) jian();
j--;
for (int i = MAX - 1; i > 0; i--)
b[i] = b[i - 1], b[i - 1] = 0;
}
}
void input() { //输入并对齐(带前导零)存储
cin >> str1 >> str2;
for (int i = 0; i < str1.size(); i++)
b[MAX - str1.size() + i] = str1[i] - '0';
for (int i = 0; i < str2.size(); i++)
a[MAX - str2.size() + i] = str2[i] - '0';
if (com(a, b) == 0 || com(b, a) == 0) chu();
//判断是否进行除法运算处理
}
int main() {
input(); print();
return 0;
}
小技巧
想让你的代码变得整齐有序?格式化来帮你!
本人用的DEV C++格式化快捷键是Ctrl+Shift+A,格式化之后代码缩进整齐有序、运算符之间都有空格,强迫症狂喜ing...(这个没法撤回哦)
本期分享就到这里了,掰掰ヾ(•ω•`)o
本文可以转载,但请注明作者,谢谢