J. Prime Game(The 2018 ACM-ICPC Asia Nanjing)(思維+線篩)
Time limit: 2000 ms
Memory limit: 1048576 kB
judge:vjudge
Description
Given a suqence of integers .
Let = and be the number of distinct prime factors of .
Please calculate
Input
The first line contains one integer — the length of the sequence.
The second line contains integers — the sequence.
Output
Print the answer to the equation.
Examples
standard input
10
99 62 10 47 53 9 83 33 15 24
10
6 7 5 5 4 9 9 1 8 12
standard output
248
134
題意
給你兩個函數:
讓你求解:
題意
剛看到這題的時候嚇壞了:我的天、素數、1e6、還累乘、求和後再求和……
但是仔細一想好像有點變化。
把每個數字看成一系列素數的集合,集合裏的素數都是它的因子,那麼兩個數相乘之後他們的素因子的集合就相當於把原來兩個數字對應的素數因子的集合合併到了一起。
我們不要把序列裏的數字看成整體,換個角度:把每個素數對答案做出的貢獻看成一個整體,我們枚舉所有出現過的素數,分別計算貢獻,最後求和即可。
那麼每個素數的貢獻就是包含它的區間的個數,如果區間內包含多個相同的素數,貢獻不疊加計算,算作一個區間。如圖:
假設序列所有的素因子一共有k個,用 表示素數 出現的第 個位置 。那麼2出現的位置有這些:0,4,8,9.
2對答案做出的貢獻:43
根據這張圖相信不難看出規律,,那麼答案就是:
代碼
#include <bits/stdc++.h>
#define _for(i, a) for(register int i = 0; i < (a); ++i)
#define _rep(i, a, b) for(register int i = (a); i <= (b); ++i)
#define sc(x) scanf("%d", &x)
using namespace std;
typedef long long LL;
const int maxn = 1000005;
inline int read() {
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;
}
struct Prime {
vector<int> arr;
int vis[1006];
void doit(int maxnum) {
for (int i = 2; i <= maxnum; ++i) {
if (!vis[i]) arr.push_back(i);
for (int j = 0; j < arr.size() && arr[j] * i <= maxnum; ++j) {
vis[arr[j] * i] = 1;
if (i % arr[j] == 0) break;
}
}
}
};
int n, a[maxn];
Prime pri;
set<int> st;
vector<LL> vv[maxn];
inline void sol() {
LL ans = 0;
_for(i, n) {
int x(a[i]);
for (int j = 0; j < pri.arr.size() && pri.arr[j] <= x; ++j) {
int val = pri.arr[j];
if (x % val == 0) {
for(; x % val == 0; ) x /= val;
vv[val].push_back(i);
st.insert(val);
}
}
if (x > 1) {
vv[x].push_back(i);
st.insert(x);
}
}
for (set<int>::iterator it = st.begin(); it != st.end(); ++it) {
int x(*it);
_for(i, vv[x].size()) {
ans += (vv[x][i] - (i ? vv[x][i - 1] : -1)) * (n - vv[x][i]);
}
}
cout << ans << "\n";
}
int main() {
pri.doit(1000);
n = read();
_for(i, n) a[i] = read();
sol();
return 0;
}