J. Prime Game(The 2018 ACM-ICPC Asia Nanjing)(思维+线筛)

J. Prime Game(The 2018 ACM-ICPC Asia Nanjing)(思维+线筛)

Time limit: 2000 ms
Memory limit: 1048576 kB
judge:vjudge

Description

Given a suqence of n n n integers a i a_i ai .
Let m u l ( l , r ) mul(l, r) mul(l,r) = ∏ i = l r a i ∏^r_{i=l} a_i i=lrai and f a c ( l , r ) fac(l, r) fac(l,r) be the number of distinct prime factors of m u l ( l , r ) mul(l, r) mul(l,r).
Please calculate ∑ i = 1 n ∑ j = i n f a c ( i , j ) ∑^n_{i=1}∑^n_{j=i}fac(i, j) i=1nj=infac(i,j)

Input

The first line contains one integer n ( 1 ≤ n ≤ 1 0 6 ) n (1 ≤ n ≤ 10^6) n(1n106) — the length of the sequence.
The second line contains n n n integers a i ( 1 ≤ i ≤ n , 1 ≤ a i ≤ 1 0 6 ) a_i (1 ≤ i ≤ n, 1 ≤ a_i ≤ 10^6) ai(1in,1ai106) — 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

题意

给你两个函数:
m u l ( l , r ) = ∏ i = l r a i mul(l, r)=∏^r_{i=l} a_i mul(l,r)=i=lrai
f a c ( l , r ) = m u l ( l , r ) 的 素 因 子 的 个 数 fac(l,r)=mul(l,r)的素因子的个数 fac(l,r)=mul(l,r)
让你求解:
∑ i = 1 n ∑ j = i n f a c ( i , j ) ∑^n_{i=1}∑^n_{j=i}fac(i, j) i=1nj=infac(i,j)

题意

刚看到这题的时候吓坏了:我的天、素数、1e6、还累乘、求和后再求和……

但是仔细一想好像有点变化。

把每个数字看成一系列素数的集合,集合里的素数都是它的因子,那么两个数相乘之后他们的素因子的集合就相当于把原来两个数字对应的素数因子的集合合并到了一起。

我们不要把序列里的数字看成整体,换个角度:把每个素数对答案做出的贡献看成一个整体,我们枚举所有出现过的素数,分别计算贡献,最后求和即可。

那么每个素数的贡献就是包含它的区间的个数,如果区间内包含多个相同的素数,贡献不叠加计算,算作一个区间。如图:

假设序列所有的素因子一共有k个,用 p o s [ x ] [ i ] pos[x][i] pos[x][i] 表示素数 x x x 出现的第 i i i 个位置 ( 0 ≤ i ) (0≤i) (0i) 。那么2出现的位置有这些:0,4,8,9.
在这里插入图片描述
2对答案做出的贡献:43
在这里插入图片描述
根据这张图相信不难看出规律,,那么答案就是:
a n s = ∑ i = 0 k − 1 x i ∑ j = 0 p o s [ x i ] . s i z e ( ) − 1 ( p o s [ x i ] [ j ] − ( j   ?   p o s [ x i ] [ j − 1 ] : − 1 ) ) ∗ ( n − p o s [ x i ] [ j ] ) ans=∑^{k-1}_{i=0}x_i∑^{pos[x_i].size()-1}_{j=0}(pos[x_i][j] - (j\ ?\ pos[x_i][j - 1] : -1)) * (n - pos[x_i][j]) ans=i=0k1xij=0pos[xi].size()1(pos[xi][j](j ? pos[xi][j1]:1))(npos[xi][j])

代码

#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;
}

猜你喜欢

转载自blog.csdn.net/weixin_42856843/article/details/105939508