PC/UVa:110504/10127
这一章因为是高精度算术,所以我总是担心整数溢出,以及超时。
这道题目就是枚举,看最短多长的全1的数可以整除输入n,根据uDebug上的测试用例,长度可以达到几千多,所以内置类型肯定是溢出了。
其实题目中已经给了提示了,找一个x,使得a * b = p,其中p = 10^0 + 10^1 + …… + 10^(x-1),a就是n,既然没让找b,那也就是p % a = 0,而p又可以拆分为若干个数字的和,所以可以利用%运算的性质,和的模等于每一项的模的和再取模。
在当前x不满足输出的情况下,需要将x加1,对应的p就变大了10 ^ (x - 1),然后可以把次数拆分成较小的,也就是利用另一个性质,积的模等于每一项的积再取模,为了避免溢出,每当积大于模数时,就可以取一次模。
代码中x表示总位数,i就是x - 1,表示这一次新增加部分的次数,viOnes是可以用内置类型表示的10的幂模n的值,用来将10 ^ i拆成较小的数。内层while循环使用的是第二个性质,外层while循环(r += tmp)是第一个性质。
根据UVa上的提交结果,适当增大viOnes可以加快运行时间。第一次提交时viOnes只计算到比n大的10的幂,时间0.180,第二次提交时viOnes计算到10^9,时间0.090。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
unsigned int n = 0;
while (cin >> n){
vector<unsigned int> viOnes;
for (size_t i = 1; i < 1000000000; i *= 10)
{
viOnes.push_back(i % n);
}
size_t x = 1, r = 1 % n;
while (r != 0){
x++;
size_t i = x - 1, tmp = 1;
while (i >= viOnes.size()){
tmp *= viOnes.back();
if (tmp >= n) tmp %= n;
i -= (viOnes.size() - 1);
}
tmp *= viOnes[i];
r += tmp;
if (r >= n) r %= n;
}
cout << x << endl;
}
return 0;
}
/*
3
7
9901
*/
探讨如何解决PC/UVa 110504/10127题目的枚举算法,通过避免整数溢出和优化运行时间,实现对全1数的高效整除检查。
229

被折叠的 条评论
为什么被折叠?



