2018-2019 ACM-ICPC, Asia Nanjing Regional Contest(J Prime Game)

J Prime Game

2018-2019 ACM-ICPC, Asia Nanjing Regional Contest(J Prime Game)_第1张图片

题意:

给出一个序列, m u l ( l , r ) = ∏ i = l r a i mul(l,r)=\prod\limits_{i=l}^ra_i mul(l,r)=i=lrai f a c ( l , r ) fac(l,r) fac(l,r)表示 m u l ( l , r ) mul(l,r) mul(l,r)的中不同的质数的个数。

问: ∑ i = 1 n ∑ j = i n f a c ( i , j ) \sum\limits_{i=1}^n\sum\limits_{j=i}^nfac(i,j) i=1nj=infac(i,j)

思路:

统计在序列中出现过的质因子的出现在哪些下标中。

举个例子:假如 2 2 2这个质因子出现在序列的 1 , 4 , 5 , 7 1,4,5,7 1457下标中,而序列的长度是 8 8 8

我们规定 [ l , r ] [l,r] [l,r]这个区间包含多个相同质数的下标的话,只认为是最前面的那个产生了贡献,这样的话。

计算某个质数产生贡献的公式就是: ∑ i = 1 k ( p o s [ p r i m e ] [ i ] − p o s [ p r i m e ] [ i − 1 ] ) ∗ ( n − p o s [ p r i m e ] [ i ] + 1 ) \sum\limits_{i=1}^k(pos[prime][i]-pos[prime][i-1])*(n-pos[prime][i]+1) i=1k(pos[prime][i]pos[prime][i1])(npos[prime][i]+1)

代码:

#include
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int N = 1e6+10;
const int inv2 = (mod+1)/2;
int p[N], tot;
bool st[N];
void init() {
	for(int i=2; i<N; i++) {
		if(!st[i]) p[tot++] = i;
		for(int j=0; j<tot&&i*p[j]<N; j++) {
			st[i*p[j]] = 1;
			if(i % p[j] == 0) break;
		}
	}
}
vector<int> v[N];


int a[N];
map<int, int> mp;
signed main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif
	init();
	int n;
	scanf("%d", &n);
	for(int i=1; i<=n; i++) {
		scanf("%d", &a[i]);
		int tmp = a[i];
		for(int j=0; 1ll*p[j]*p[j]<=tmp; j++) {
			if(tmp % p[j] == 0) {
				mp[p[j]] = 1;
				if(v[p[j]].size() == 0) v[p[j]].push_back(0);
				v[p[j]].push_back(i);
				while(tmp % p[j] == 0) tmp /= p[j];
			}
		}
		if(tmp > 1) {
			mp[tmp] = 1;
			if(v[tmp].size() == 0) v[tmp].push_back(0);
			v[tmp].push_back(i);
		}
	}
	ll ans = 0;
	for(auto it : mp) {
		int x = it.first, y = v[x].size();
		for(int i=1; i<y; i++) {
			ans += 1ll * (n-v[x][i]+1) * (v[x][i]-v[x][i-1]);
		}
	}
	cout << ans << endl;
    return 0;
}

你可能感兴趣的:(思维,题解,数论,算法,c++)