题目抽象:给你一个整数序列。 对于它的每个非空的子集区间,有多少个整数不能整除其它数。求每个非空子集区间的这些数的总和。
分析:用L[i],R[i]表示a[i]中最近的约数。
超时代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include <queue> 11 #include <sstream> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 0x4ffffff; 15 const double EXP = 1E-5; 16 const LL mod = 1e9+7; 17 const int MS= 1E5+5; 18 const int MS2 = 1e4+1; 19 20 int a[MS]; 21 int L[MS]; 22 int R[MS]; 23 24 int main() 25 { 26 int n; 27 while(scanf("%d",&n)!=EOF) 28 { 29 for(int i = 1;i<=n;i++) 30 scanf("%d",&a[i]); 31 a[0] = 1; 32 a[n+1] = 1; 33 34 for(int i = 1;i<=n;i++) 35 { 36 for(int j = i-1;j>=0;j--) 37 { 38 if(a[i] % a[j] == 0) 39 { 40 L[i] = j; 41 break; 42 } 43 } 44 45 for(int j = i+1;j<=n+1;j++) 46 { 47 if(a[i] % a[j] == 0) 48 { 49 R[i] = j; 50 break; 51 } 52 } 53 } 54 LL ans= 0; 55 for(int i =1;i<=n;i++) 56 { 57 ans += (i - L[i]) * (R[i] - i); 58 ans %=mod; 59 } 60 printf("%lld\n",ans); 61 } 62 return 0; 63 }
优化: 由于每个整数不大于10000,我们可以预处理出每个数的约数。在处理L[i]和R[i]中,用pre数组来表示前面出现的整数。见代码。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <string> 7 #include <vector> 8 #include <set> 9 #include <map> 10 #include <queue> 11 #include <sstream> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 0x4ffffff; 15 const double EXP = 1E-5; 16 const LL mod = 1e9+7; 17 const int MS= 1E5+5; 18 const int MS2 = 1e4+1; 19 20 int a[MS]; 21 int L[MS]; 22 int R[MS]; 23 int pre[MS]; 24 vector<int> vec[MS]; 25 26 void init() 27 { 28 for(int i = 1;i<MS2;i++) 29 { 30 for(int j = i;j <MS2;j+=i) 31 { 32 vec[j].push_back(i); 33 } 34 } 35 } 36 37 int main() 38 { 39 init(); 40 int n; 41 while(scanf("%d",&n)!=EOF) 42 { 43 for(int i =1;i<=n;i++) 44 scanf("%d",&a[i]); 45 memset(pre,0,sizeof(pre)); 46 for(int i = 1;i<=n;i++) 47 { 48 int t = 0; 49 for(int j =0;j<vec[a[i]].size();j++) 50 { 51 if(pre[vec[a[i]][j]]) 52 t = max(t,pre[vec[a[i]][j]]); 53 } 54 L[i] = t; 55 pre[a[i]] = i; 56 } 57 58 memset(pre,0,sizeof(pre)); 59 for(int i = n;i>0;i--) 60 { 61 int t = n+1; 62 for(int j = 0;j<vec[a[i]].size();j++) 63 { 64 if(pre[vec[a[i]][j]]) 65 { 66 t = min(t,pre[vec[a[i]][j]]); 67 } 68 } 69 R[i] = t; 70 pre[a[i]] = i; 71 } 72 LL ans= 0; 73 for(int i = 1;i<=n;i++) 74 { 75 ans += (i - L[i]) * (R[i] - i); 76 ans %= mod; 77 } 78 printf("%lld\n",ans); 79 } 80 return 0; 81 }
时间: 2024-10-10 01:27:28