因为区间 gcd 的变换不会超过 log 个,所以我们可以暴力枚举区间起点,复杂度是 n*logn 的
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define rep(i,a,b) for(int i=a;i<=b;++i) 4 #define fd(i,a,b) for(int i=a;i>=b;--i) 5 const int maxn=100010,mod=998244353; 6 template <typename T> bool check_Max(T &x, const T&y) {return x<y?x=y,false:true;} 7 template <typename T> bool check_Min(T &x, const T&y) {return x>y?x=y,false:true;} 8 inline int gi() { 9 int x=0; char o; bool f=true; for(;!isdigit(o=getchar());) if(o=='-') f=false; 10 for(;isdigit(o);o=getchar()) x=(x<<1)+(x<<3)+(o&15); return f?x:~x+1; 11 } 12 template <typename T> inline void Md(T &x) {if(x>=mod) x-=mod;} 13 int gcd(int x,int y) { return x?gcd(y%x,x):y;} 14 int gd1[maxn],gd2[maxn],nt[maxn],a[maxn],n,ans; 15 int main() { 16 #ifndef ONLINE_JUDGE 17 freopen("10.in","r",stdin); 18 #endif 19 n=gi(); rep(i,1,n) gd1[i]=gd2[i]=a[i]=gi(); 20 rep(i,2,n) gd1[i]=gcd(gd1[i-1],gd1[i]); fd(i,n-1,1) gd2[i]=gcd(gd2[i+1],gd2[i]); 21 rep(i,2,n) nt[i]=gd2[i]==gd2[i-1]?nt[i-1]:i-1; 22 rep(i,2,n) { 23 int pos=gd1[i-1]; if(i>2) Md(ans+=pos%mod); 24 int L=n; 25 while(L>i) { 26 int R=max(i+1,nt[L]+1); pos=gcd(pos,gd2[R]); 27 // printf("i=%d L=%d R=%d pos=%d--\n",i,L,R,pos);//de bug 28 Md(ans+=1LL*pos*(L-R+1)%mod); L=R-1; 29 } 30 } 31 int L=n-1,R,pos=gd2[L]; 32 while(L>1) { 33 R=max(2,nt[L]+1),pos=gd2[R]; 34 // peintf("L=%d R=%d pos=%d\n",L,R,pos); //de bug 35 Md(ans+=1LL*pos*(L-R+1)%mod); L=R-1; 36 } 37 printf("%d\n",ans); 38 return 0; 39 }
今天的水题计划就到这里了,顺带提一句,今天S8世界总决赛 小组赛IG vs GRX时Stitch 的反向Q,连皮肤都和当年韦神的一样
放个图感受一下