題意:求for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) sum += f[i][j]; f[i][j]表示在序列從 i 位乘到第 j 位所造成的新的數的 不一樣質因子的個數.ios
思路:說是話,拿到題仍是一開始想着能不能進行遞推,好比先將每個數進行 質因分解 而後用set不斷更新統計個數來求和。但這樣不管怎樣都沒法優化 (n^2) ,因此換思路再想。c++
就突然想到了之前有一道作過的原題,題意是:給定一個長度爲n的序列,而後求出每個子區間不一樣數的個數和。而這一道題就是組合計數,計算每個位置上的值對最後區間計數所產生的貢獻。函數
而這道題相似,略微修改便是每個位置上不僅一個值(分解可能獲得多個質因子),因此就用set來存放。優化
上面這幅圖,座標軸上表示座標,座標軸下表示每一個位置set所存放對應數的質因子數。好比咱們對全部位置的5的貢獻值進行計算。spa
位置座標2:因爲這個5要產生貢獻,即其左邊起始下標要從 1 開始,直到它自己的座標 2. 其右邊的開始座標從它自己開始 2 一直延申到座標軸右端. 因此 左 x 右 = (2-0) x (7-2+1) = 10;code
位置座標4:要使這個位置的5產生貢獻,因爲咱們對上一個5右邊全部區間進行了計算,因此在計算這個5的貢獻的時候咱們要從它上一個5的位置的下一位開始到它自己,即從 3-4,而其右端也是延申到右端點,因此 (4-2) x (7-4+1) = 8;blog
因此計算某個數的貢獻,即 其左邊第一個出現的下一位開始到他自己位置爲左端點取值範圍,從他自己開始到座標軸右端點爲其區間右端點取值範圍,而左乘以右則爲全部區間貢獻總和。ci
#include <bits/stdc++.h> #define IOS ios::sync_with_stdio(0); cin.tie(0); #define mp make_pair using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const double Pi = acos(-1.0); const double esp = 1e-9; const int inf = 0x3f3f3f3f; const int maxn = 1e5+7; const int maxm = 1e6+7; const int mod = 1e9+7; //全部模板默認 prime[],powe[]從下標0開始取 const int MAXL = 1e6+7; //int phi[MAXL];//歐拉函數 int tot; int prim[MAXL];//素數表 int cnt; int vis[MAXL]; //int powe[MAXL];//質數冪 int cur; int pp[maxm]; set<int>qq[maxm]; set<int>::iterator it; int a[maxm]; int getPrime(){ int i ,j; int cnt = 0; memset(vis,0,sizeof(0)); vis[0] = vis[1] = 1; for(i=2;i<=MAXL;++i) { if(!vis[i]) vis[i]= prim[cnt++]= i; for(j=0;j<cnt&&i*prim[j]<=MAXL;++j){ vis[i*prim[j]] = 1; if(i%prim[j]==0) break; } } return cnt; } int getfac(int n,int cnt,int pos){ for(int i=0;prim[i]*prim[i]<=n;i++){ if(n%prim[i]==0) { qq[pos].insert(prim[i]); pp[prim[i]] = 0; while(n%prim[i]==0) n /= prim[i]; } } if(n>1) qq[pos].insert(n); } int main(){ int n; scanf("%d",&n); cnt = getPrime(); for(int i=1;i<=n;i++){ scanf("%d",a+i); getfac(a[i],cnt,i); } ll sum = 0; for(int i=1;i<=n;i++){ for(it = qq[i].begin();it != qq[i].end(); it++){ int tmp = *it; int k = pp[tmp]; pp[tmp] = i; sum += (ll) (i-k)*(n-i+1); } } printf("%lld\n",sum); }