如果枚举区间的话是O(n^2)的复杂度一定会T,所以考虑每个数a[i]对答案的贡献,则只需找到a[i]的约数中在左边最靠近a[i]的和在右边最靠近a[i]的那两个约数位置,然后扫一遍统计答案即可。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 typedef long long ll; 7 const int INF = 0x3f; 8 const int MOD = 1000000007; 9 const int N = 100001; 10 int a[N]; 11 int l[N]; 12 int r[N]; 13 int mp[N]; 14 15 int main () 16 { 17 int n; 18 while ( scanf("%d", &n) != EOF ) 19 { 20 for ( int i = 1; i <= n; i++ ) 21 { 22 scanf("%d", a + i); 23 l[i] = 0; 24 r[i] = n + 1; 25 } 26 memset( mp, -1, sizeof(mp) ); 27 for ( int i = 1; i <= n; i++ ) 28 { 29 for ( int j = 1; j * j <= a[i]; j++ ) 30 { 31 if ( a[i] % j == 0 ) 32 { 33 l[i] = max( l[i], mp[j] ); 34 l[i] = max( l[i], mp[a[i] / j] ); 35 } 36 } 37 mp[a[i]] = i; 38 } 39 memset( mp, INF, sizeof(mp) ); 40 for ( int i = n; i >= 1; i-- ) 41 { 42 for ( int j = 1; j * j <= a[i]; j++ ) 43 { 44 if ( a[i] % j == 0 ) 45 { 46 r[i] = min( r[i], mp[j] ); 47 r[i] = min( r[i], mp[a[i] / j] ); 48 } 49 } 50 mp[a[i]] = i; 51 } 52 int ans = 0; 53 for ( int i = 1; i <= n; i++ ) 54 { 55 ans = ( ans + ( ll ) ( i - l[i] ) * ( r[i] - i ) ) % MOD; 56 } 57 printf("%d ", ans); 58 } 59 return 0; 60 }