[关闭]
@tenlee 2015-07-24T10:59:16.000000Z 字数 2982 阅读 1603

HDU 5289 OO’s Sequence(2015多校联合)

HDUOJ 题解

题目链接:戳我


题目大意:

f(l, r)代表一个l,r区间内,符合任选i,j (l <= j <= r && j != i),有ai % aj != 0的i的个数
ni=1nj=if(i,j)mod(109+7)

样例解释

5 即为n,代表有n个数,n <= 105
1 2 3 4 5 分别为上面的 n 个数,0 < ai <= 10000
f(1,1) = {1} = 1; f(1,2) = {1} = 1; f(1,3) = {1} = 1; f(1,4) = {1} = 1; f(1,5) = {1} = 1
f(2,2) = {2} =1; f(2,3) = {2,3} = 2; f(2,4) = {2,3} = 2; f(2,5) = {2,3,5} = 3
f(3,3) = {3} = 1; f(3,4) = {3,4} = 2; f(3,5) = {3,4,5} = 3;
f(4,4) = {4} = 1; f(4, 5) = {4,5} = 2;
f(5,5) = {5} = 1;
故所有加起来为23

解题思路

分析:数组长度为105,而每个数不超多 10000
假设一个数的位置是 pos 值为x,那个在x左侧和x最近的属于x的因子的位置是l,在x右侧和x最近的属于x因子的位置是r,那么在(l+1, r-1)这个区间内,任选左区间一个位置ll,在任选右区间一个位置rr,那么x必为此区间符合条件的一个数
num=(xl)(rx)
只需枚举每一个位置,极其l,r即可

思路:

可以先预处理10000个数的每个数的因子,在枚举每一个位置的时候即可知道最左的因子和最右的因子了

代码:

452ms

  1. //Author LJH
  2. //www.cnblogs.com/tenlee
  3. #include <cstdio>
  4. #include <cstdlib>
  5. #include <cstring>
  6. #include <cctype>
  7. #include <cmath>
  8. #include <algorithm>
  9. #include <vector>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #define clc(a, b) memset(a, b, sizeof(a))
  14. using namespace std;
  15. const int inf = 0x3f;
  16. const int INF = 0x3f3f3f3f;
  17. const int maxn = 1e5+5;
  18. const long long mod = 1e9+7;
  19. int a[maxn], ha[maxn], l[maxn], r[maxn], pre[maxn];
  20. vector<int> v[maxn];
  21. void Init()
  22. {
  23. v[1].push_back(1);
  24. for(int i = 2; i <= maxn; i++)
  25. {
  26. for(int j = 2; i*j <= maxn; j++)
  27. {
  28. v[j*i].push_back(i);
  29. }
  30. v[i].push_back(1);
  31. v[i].push_back(i);
  32. }
  33. }
  34. int main()
  35. {
  36. //freopen("1001.in", "r", stdin);
  37. int n, i, j, k = 0;
  38. long long ans;
  39. Init();
  40. while(~scanf("%d", &n))
  41. {
  42. for(i = 1; i <= n; i++)
  43. {
  44. scanf("%d", &a[i]);
  45. }
  46. clc(pre, 0);
  47. for(i = 1; i <= n; i++)
  48. {
  49. l[i] = 1;
  50. k = a[i];
  51. for(j = 0; j < (int)v[k].size(); j++)
  52. {
  53. if(pre[v[k][j]] != 0)
  54. {
  55. l[i] = max(l[i], pre[v[k][j]] + 1);
  56. }
  57. }
  58. //if(a[i] == a[i-1]) l[i] = i;
  59. pre[a[i]] = i;
  60. }
  61. clc(pre, 0);
  62. for(i = n; i > 0; i--)
  63. {
  64. r[i] = n;
  65. k = a[i];
  66. for(j = 0; j < (int)v[k].size(); j++)
  67. {
  68. if(pre[v[k][j]] != 0)
  69. {
  70. r[i] = min(r[i], pre[v[k][j]] - 1);
  71. }
  72. }
  73. //if(a[i]==a[i+1]) r[i] = i;
  74. pre[a[i]] = i;
  75. }
  76. ans = 0;
  77. for(i = 1; i <= n; i++)
  78. {
  79. ans = (ans + (long long)( i - l[i] + 1) * (long long)(r[i] - i + 1) % mod) % mod;
  80. if(ans > mod) ans -= mod;
  81. }
  82. printf("%lld\n", ans % mod);
  83. }
  84. return 0;
  85. }

标程代码:
1232ms

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<vector>
  4. #define N 100010
  5. #define P 1000000007
  6. using namespace std;
  7. int n,i,a[N],j,t,q[N];
  8. int l[N],tmp,r[N];
  9. long long a1,a2,ans;
  10. vector<int> vec[10010];
  11. int main()
  12. {
  13. // freopen("a.in","r",stdin);
  14. // freopen("a.out","w",stdout);
  15. while (scanf("%d",&n)!=EOF)
  16. {
  17. for (i=101;i<=10000;i++)
  18. vec[i].clear();
  19. for (i=1;i<=n;i++)
  20. {
  21. l[i]=0;
  22. r[i]=n+1;
  23. scanf("%d",&a[i]);
  24. if (a[i]>100)
  25. vec[a[i]].push_back(i);
  26. }
  27. for (j=1;j<=100;j++)
  28. {
  29. tmp=0;
  30. for (i=1;i<=n;i++)
  31. {
  32. if (a[i]%j==0) l[i]=max(l[i],tmp);
  33. if (a[i]==j)
  34. tmp=i;
  35. }
  36. tmp=n+1;
  37. for (i=n;i>=1;i--)
  38. {
  39. if (a[i]%j==0) r[i]=min(r[i],tmp);
  40. if (a[i]==j)
  41. tmp=i;
  42. }
  43. }
  44. for (i=101;i<=10000;i++)
  45. q[i]=0;
  46. for (i=1;i<=n;i++)
  47. if (a[i]>100)
  48. {
  49. for (j=a[i];j<=10000;j=j+a[i])
  50. while ((q[j]<vec[j].size())&&(vec[j][q[j]]<i))
  51. {
  52. r[vec[j][q[j]]]=min(r[vec[j][q[j]]],i);
  53. if ((q[j]<vec[j].size()-1)&&(vec[j][q[j]+1]<i))
  54. q[j]++;
  55. else
  56. break;
  57. }
  58. }
  59. for (i=101;i<=10000;i++)
  60. q[i]=vec[i].size()-1;
  61. for (i=n;i>=1;i--)
  62. if (a[i]>100)
  63. {
  64. for (j=a[i];j<=10000;j=j+a[i])
  65. while ((q[j]>=0)&&(vec[j][q[j]]>i))
  66. {
  67. l[vec[j][q[j]]]=max(l[vec[j][q[j]]],i);
  68. if ((q[j]>0)&&(vec[j][q[j]-1]>i))
  69. q[j]--;
  70. else
  71. break;
  72. }
  73. }
  74. ans=0;
  75. for (i=1;i<=n;i++)
  76. {
  77. a1=r[i]-i;
  78. a2=i-l[i];
  79. ans=(ans+a1*a2)%P;
  80. }
  81. printf("%I64d\n",ans);
  82. }
  83. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注