这道题我一开始想的是40分的做法(纯粹暴力),之后想到了80分的代码,思路是这样的:
首先,1操作直接处理,把2操作花O(sqrt(n))时间给x分解质因数,例420=2*2*3*5*7,开一个vis数组(初始时为true),之后把所有有过的质因子枚举倍数,例如3,枚举把vis[3],vis[6],vis[9],vis[12],vis[15]......给排除,最后扫一遍得到答案。最差情况为2*3*5*7*11*13, n/2 + n/3 + n/5 + n/7 + n/11 + n/13≈2n
时间复杂度为O(nq) (40分做法带个log)
代码:
#include <iostream>
#include <cstring>
using namespace std;
int a[100005];
bool vis[100005];
int main()
{
int n, q;
cin >> n >> q;
for (int i = 1; i <= n; ++i)
{
cin >> a[i];
}
for (int l = 1; l <= q; ++l)
{
int op;
cin >> op;
if (op == 1)
{
int x, y;
cin >> x >> y;
a[x] = y;
}
else
{
memset(vis, true, sizeof(vis));
int y, y2;
cin >> y;
y2 = y;
for (int i = 2; i * i <= y2; ++i)
{
if (y % i == 0)
{
for (int j = 1; i * j <= n; ++j)
{
vis[i * j] = false;
}
while (y % i == 0) y /= i;
}
}
if (y != 1)
{
for (int j = 1; y * j <= n; ++j)
{
vis[y * j] = false;
}
}
int sum = 0;
for (int i = 1; i <= n; ++i)
{
if (vis[i]) sum += a[i];
}
cout << sum << endl;
}
}
return 0;
}
虽然我们目前没有满分做法,但我们可以在之后多想一步,也许会有新的发现。