SP32079 ADAGF - Ada and Greenflies
题传
无聊水水经验
题意:求
考虑枚举
不难发现,以
那么段数是多少呢?因为每当
有了这个结论后,我们直接考虑增量计算,每次直接继承
复杂度分析:每次至少让序列中的一个数减半,所以复杂度
Code
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <cctype>
#include <vector>
#include <cstdlib>
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f;
//const int mo=998244353;
inline int read(){
char ch=getchar();int x=0, f=1;
while(!isdigit(ch)){if(ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
inline void write(int x){
if(x<0) putchar('-'), x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
const int N=5e5+10;
vector < pair<int, int> > R[N];
int a[N];
int gcd(int x, int y){
return y?gcd(y, x%y):x;
}
long long ans;
void solve(int n){
for(int i=1; i<=n; ++i){
int x=a[i], pos=i;
for(int j=0; j<R[i-1].size(); ++j){
pair <int, int> lst=R[i-1][j];
int tmp=gcd(x, lst.second);
if(tmp!=x) R[i].push_back(make_pair(pos, x));
pos=lst.first;x=tmp;
}
R[i].push_back(make_pair(pos, x));
int up=R[i].size();
for(int j=up-1; j; --j){
int l=R[i][j].first, r=R[i][j-1].first;
int g=R[i][j].second;
long long gx=1ll*(r-l)*g;
ans=(ans+gx);
}
int l=R[i][0].first, g=R[i][0].second;
long long gx=1ll*(i-l+1)*g;
ans=(ans+gx);
}
}
signed main(){
int n; scanf("%d",&n);
for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
solve(n);printf("%lld", ans);
return 0;
}