很容易想到考虑每个质因子对全局的贡献。
思路就是考虑一边。
每个质因可能因为前或后已经出现过质因子了难以计算。不妨对每个质因子采用如下策略,每个质因子的管辖范围是当前位置到前一个质因子位置这段区间,以及到最后的区间。可以想到这样的计数方法是不会重复的。
关于实现:
枚举质因子的时候注意循环条件,我一开始是prime[j] < a[i],这样最坏会遍历cnt遍。一种更好的方法是类似求因子,当然还要注意本身就是质因子的情况。
#pragma warning(disable:4996) #include<iostream> #include<algorithm> #include<bitset> #include<tuple> #include<unordered_map> #include<fstream> #include<iomanip> #include<string> #include<cmath> #include<cstring> #include<vector> #include<map> #include<set> #include<list> #include<queue> #include<stack> #include<sstream> #include<cstdio> #include<ctime> #include<cstdlib> #define pb push_back #define INF 0x3f3f3f3f #define inf 0x7FFFFFFF #define moD 1000000003 #define pii pair<ll,ll> #define eps 1e-8 #define equals(a,b) (fabs(a-b)<eps) #define bug puts("bug") #define re register #define fi first #define se second typedef long long ll; typedef unsigned long long ull; const ll MOD = 1e6 + 7; const int maxn = 1e6 +5; const double Inf = 10000.0; const double PI = acos(-1.0); using namespace std; int prime[maxn]; int vis[maxn]; int lastpos[maxn]; ll a[maxn]; int euler_sieve(int n) { int cnt = 0; for (int i = 2; i <= n; i++) { if (!vis[i]) prime[cnt++] = i; for (int j = 0; j < cnt; j++) { if (i * prime[j] > n) break; vis[i * prime[j]] = 1; if (i % prime[j] == 0) break; } } return cnt; } int readint() { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } int readll() { ll x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } void Put(ll x) //输出 { if (x > 9) Put(x / 10); putchar(x % 10 + '0'); } int main() { memset(lastpos, -1, sizeof lastpos); int cnt = euler_sieve(maxn); int n; ll res = 0; n = readint(); for (int i = 0; i < n; i++) a[i] = readll(); for (int i = 0; i < n; i++) { for (int j = 0; j < cnt && (ll)prime[j] * prime[j] <= a[i]; j++) { if (a[i] % prime[j] == 0) { if (lastpos[prime[j]] == -1) res += (ll)(1 + i) * (n - i); else res += (ll)(i - lastpos[prime[j]]) * (n - i); lastpos[prime[j]] = i; } while (a[i] % prime[j] == 0) a[i] /= prime[j]; } if (a[i] > 1) if (lastpos[a[i]] == -1) res += (ll)(1 + i) * (n - i), lastpos[a[i]] = i; else res += (ll)(n - i) * (i - lastpos[a[i]]), lastpos[a[i]] = i; } Put(res); }