1. 程式人生 > >【ACM-ICPC 2018 南京現場賽 】 J.Prime Game ---- 思維+素數篩

【ACM-ICPC 2018 南京現場賽 】 J.Prime Game ---- 思維+素數篩

題目:
在這裡插入圖片描述

做法: 計算出來每個數的質因子在各個區間的貢獻。
以第二組樣例為例:
在這裡插入圖片描述
第一個元素的素因子2:
它能貢獻的區間有[1,1],[1,2],……,[1,10] 10個區間
第一個元素的素因子3:
它能貢獻的區間有[1,1],[1,2],……,[1,10] 10個區間
當前sum = 10+10
第二個元素的素因子7:
它能貢獻的區間有[1,2],[1,3],……,[1,10] 9個區間
它能貢獻的區間有[2,2],[2,3],……,[2,10] 9個區間
當前sum = 10+10 +9*2
同理第三個元素的素因子5算好後 sum = 10+10+9*2+8*3
當考慮第四元素的素因子5時,發現i = 3時的素因子5


在區間:
[1,3],[1,4],……,[1,10]
[2,3],[2,4],……,[2,10]
[3,3],[3,4],……,[3,10]
這3*8個區間中已經貢獻過,所以我們從當前i = 4位置向後考慮 這個位置的素因子5對區間的貢獻為 7
sum = 10+10+9*2+8*3+7

最終到n = 10,sum = 10+10+9*2+8*3+7+6*4+5*5+4+0+2*4+1+3=134
依次向後推理,我們現在每個素因子i貢獻公式為:

ansi=(nprime[i][pos]+1)(prime[i][pos]prime[i][pos1])ans_i = (n-prime[i][pos]+1)*(prime[i][pos]-prime[i][pos-1])


所以我們分解出質因子,把他們的位置放進vector, 掃一遍素數即可

程式碼

#include<bits/stdc++.h>
using namespace std;

#define IO          ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pb(x)       push_back(x)
#define sz(x)       (int)(x).size()
#define sc(x)       scanf("%d",&x)
#define abs(x) ((x)<0 ? -(x) : x) #define all(x) x.begin(),x.end() #define mk(x,y) make_pair(x,y) #define fin freopen("in.txt","r",stdin) #define fout freopen("out.txt","w",stdout) typedef long long ll; const int mod = 1e9+7; const double PI = 4*atan(1.0); const int maxm = 1e8+5; const int maxn = 1e4+5; const int INF = 0x3f3f3f3f; const ll LINF = 1ll<<62; int a[maxn],n,tot; int prime[maxn]; bool isprime[maxn]; vector<int> vec[maxn]; void prime_table() { memset(isprime,true,sizeof(isprime)); isprime[0] = isprime[1] = false; for(int i=2;i<maxn;i++){ prime[tot++] = i; if(isprime[i]){ for(int j=i*i;j<maxn;j+=i) isprime[j] = false; } } } void dec(int pos) { int t = a[pos]; for(int j=0;j<tot && prime[j]*prime[j]<=t;j++) { if(t%prime[j] == 0){ vec[prime[j]].pb(pos); while(t%prime[j] == 0) t/=prime[j]; } } if(t>1) vec[t].pb(pos); } int main() { // fin; IO; prime_table(); cin>>n; for(int i=2;i<maxn;i++) vec[i].pb(0); for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++) dec(i); ll res = 0; for(int i=0;i<tot;i++){ for(int j=1;j<sz(vec[prime[i]]);j++){ res = res+(vec[prime[i]][j] - vec[prime[i]][j-1])*(n-vec[prime[i]][j]+1); } } cout<<res<<endl; return 0; }