2018-2019 Asia Nanjing Regional Contest练习总结
题目:Prime Game
题意:
给出一个序列,定义了 mul(l, r) 为 al 到ar 的乘积,而fac(l, r) 为mul(l, r) 不相同质因数的个数,让你算出这个序列所有子区间的fac和。
思路:
这个主要理清对于序列中的一个数 a,找出它的贡献段,对于序列中任意一个aw ,它说分解出来的每一个不同素数(z),贡献为( w-point[ z ] )* (n-w+1) 【point为存储素数上次出现位置的数组,此处下标从1开始】。有了贡献的计算方法就很好搞了,不过要注意范围,在计数这个贡献时,乘积会爆int (WA在第7个点)。
解题
#include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <string> #include <cstring> #include <map> #include <set> using namespace std; const long long N = 1e10 + 7; const int maxn = 1e6 + 5; const long long INF = 8e18; typedef long long ll; #define for0(i,n) for(int i = 0;i < n;i++) #define for1(i,n) for(int i = 1;i <= n;i++) int point[maxn]; // 存该素数上次的出现位置 int prime_if[maxn]; int prime[maxn],x; void oulasai(int n) { prime_if[1] = 1; for(ll i=2;i<=n;i++) { if(!prime_if[i]) prime[x++]=i; for(int j=0;j<x;j++) { if(i*prime[j]>n) break; prime_if[i*prime[j]]=1; if(i%prime[j]==0) break; } } } int main() { //ios::sync_with_stdio(false); oulasai(maxn); int n; cin >> n; ll sum = 0; for1(i,n){ int y; cin >> y; if(y == 1) continue; if(prime_if[y]){ for(int j = 0;j < x;j++){ if(prime[j] * prime[j] > y) break; if(y % prime[j] == 0){ sum += (ll)(n-i+1) * (i-point[prime[j]]); point[ prime[j] ] = i; while(y % prime[j] == 0) y /= prime[j]; } } } if(!prime_if[y]){ //最后一次出现的素数 sum += (ll)(n-i+1)*(i-point[y]); point[y] = i; } } cout << sum << endl; return 0; }

浙公网安备 33010602011771号