题目链接:点我啊╭(╯^╰)╮
题目大意:
n n n 个数,让你求所有连续子区间的 G C D GCD GCD 的和
解题思路:
因为一共有
n
(
n
−
1
)
/
2
n(n-1)/2
n(n−1)/2 个子区间,暴力是肯定不行的(别真的以为不行)
那么
n
n
n 个数作
G
C
D
GCD
GCD,最多只会作
l
o
g
n
logn
logn 次,也可以说会改变
l
o
g
n
logn
logn 次,所以记录一下每个数下一个会改变的数的位置即可,复杂度
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
核心:区间 G C D GCD GCD、与、或 都是这个思路,最多改变 l o g n logn logn 次
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const int maxn = 5e5 + 5;
const int mod = 1e9 + 7;
int n, ans, a[maxn];
int l[maxn], v[maxn];
int main() {
scanf("%d", &n);
for(int i=1; i<=n; i++)
scanf("%d", a+i), v[i] = a[i], l[i] = i;
for(int i=1; i<=n; i++)
for(int j=i; j; j=l[j]-1) {
v[j] = __gcd(v[j], a[i]); // j ~ i的gcd值
while(l[j]>1 && __gcd(a[i], v[l[j]-1])==__gcd(a[i], v[j]))
l[j] = l[l[j]-1];
ans = (ans + 1LL * v[j] * (j-l[j]+1)) % mod;
}
printf("%d", ans);
}
那么问题来了,下面这一串代码也能神奇的ac这道题,只能说数据是个屁
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 5e5+10;
ll n, a[maxn], ans;
int main(){
scanf("%lld", &n);
for(int i=1; i<=n; i++) scanf("%lld", a+i);
ll c = a[1];
for(int i=2; i<=n; i++) c = __gcd(c, a[i]);
for(int i=1; i<=n; i++){
ll x = a[i];
for(int j=i; j<=n; j++){
x = __gcd(x, a[j]);
if(x==c){
ans += 1LL*(n-j+1)*c;
ans %= mod;
break;
}
ans += x;
ans %= mod;
}
}
printf("%lld\n", ans);
}