我想存储从1到10 ^ 6的所有数字的所有除数。但这似乎太慢了。这是我的代码的preprocess()函数:
for(int i=1; i<=1000000; i++)
{
for(int j=1; j<=i/2; j++)
{
if(i%j==0)
divi[i][j] = true;
}
}
我使用了这样的地图容器:
map <int, bool> divi[1000010];
然后我试图找到两个给定数字的公约数。
preprocess();
int T, A, B;
cin >> T;
while(T--)
{
cin >> A >> B;
int common = 0;
for(it = divi[A].begin(); it!=divi[A].end(); it++)
{
if(divi[B][it->first]==true)
common++;
}
cout << common << endl;
我现在该如何处理以使其足够快?
答案 0 :(得分:4)
除了使用std::map
本身很昂贵(不能使用数组吗?)这一事实之外,快速的数字胜利只能达到数字的平方根。内循环。
for (int j = 1; j * j <= i; j++)
(注意平方j
比计算i
的平方根要便宜,并让你远离浮点计算。)
必须注意,如果j
是除数,则i / j
也除数。所以你还需要替换
divi[i][j] = true;
与
divi[i][j] = divi[i][i / j] = true;
此优化以计算单数的除数为中心。有更快的方法来获取 set 数字的除数,但我的方法可能就足够了。如果不是,请关注。
答案 1 :(得分:1)
这取决于你想要什么:如果你只想要一些特定数字的公约数,那么欧几里得算法就是解决方案。
如果你真的想要一个所有数字1..n的所有除数的列表,一个解决方案就是(类似于Sieve):
for(int I=1;I<=sqrt(n);++I) {
for(int j=I;j*I<=n;++j) divi[I*j][j]=divi[I*j][I]=true;
}
原始代码的代码复杂度为O(N ^ 2),第一个答案为O(N ^ 1.5)。我相信新公式是O(N * log N)