需要存储每个质因数存在的位置,然后计算出每个质因数的贡献和。
题目链接
题意
Mul(i,j)代表的是第i到j个数字的乘积,然后fac(i,j)代表这个乘积的不同的质因子的个数。现在让你求出n^2段区间内的fac(i,j)和.
思路
显然不能用N^2的做法。我们可以先把每个数字质因数分解,存储每个质因数所在的位置。比如说序列为22,33。 那么11这个质因数存在的位置就是1,2. 然后我们枚举每个质因数的每个存在的位置,计算贡献和。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| #include <iostream> #include <algorithm> #include <stdio.h> #include <string> #include <cstring> const int maxn = 1000000; using namespace std; typedef long long ll; vector<int>V[maxn + 5]; int tot,a[maxn + 5]; bool is[maxn + 5]; int prime[maxn + 5],n; void Prime() { memset(is, 0, sizeof(is)); for(int i = 2; i <= maxn; ++i) { if(!is[i]) { prime[++tot] = i; for(int j = i + i; j <= maxn; j += i) { is[j] = 1; } } } }
void solve() { for(int i = 1; i <= n; ++i){ for(int j = 1; prime[j] * prime[j] <= a[i] && j <= tot; ++j) { if(a[i] % prime[j] == 0) { V[prime[j]].push_back(i); while(a[i] % prime[j] == 0) a[i] /= prime[j]; } } if(a[i] != 1) V[a[i]].push_back(i); } } int main() { tot = 0; Prime(); cin >> n; for(int i = 1; i <= n; ++i) scanf("%d",&a[i]); solve(); ll ans = 0; for(int i = 1; i < maxn; i ++) { if(V[i].size() == 0)continue; for(int j = 0; j < V[i].size(); ++j) { if(j == 0) ans += 1ll * (n - V[i][j] + 1) * (V[i][j]); else ans += 1ll *(n - V[i][j] + 1) * (V[i][j] - V[i][j - 1]); } } cout << ans << '\n'; }
|