題目鏈接:點我啊╭(╯^╰)╮
題目大意:
個數,讓你求所有連續子區間的 的和
解題思路:
因爲一共有 個子區間,暴力是肯定不行的(別真的以爲不行)
那麼 個數作 ,最多隻會作 次,也可以說會改變 次,所以記錄一下每個數下一個會改變的數的位置即可,複雜度
代碼思路:
過於簡單
核心:區間、與、或 都是這個思路,最多改變 次
#include<bits/stdc++.h>
const int N=500010, P=1000000007;
int n, ans, a[N], l[N], v[N];
int gcd(int a,int b) {
return b?gcd(b,a%b):a;
}
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]);
while(l[j]>1 && gcd(a[i],v[l[j]-1])==gcd(a[i],v[j]))
l[j] = l[l[j]-1];
ans = (1LL*v[j]*(j-l[j]+1)+ans)%P;
}
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);
}