码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 5288 OO’s Sequence

时间:2015-07-25 00:07:22      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5288

OO has got a array A of size n ,defined a function f(l,r) represent the number of i (l<=i<=r) , that there‘s no j(l<=j<=r,j<>i) satisfy ai mod aj=0,now OO want to know

∑(i=1->n)∑(j=i->n)f(i,j) mod 109+7.

Input
There are multiple test cases. Please process till EOF.
In each test case: 
First line: an integer n(n<=10^5) indicating the size of array
Second line:contain n numbers ai(0<ai<=10000)
 
Output
For each tests: ouput a line contain a number ans.
 
Sample Input
5
1 2 3 4 5
 
Sample Output
23

题意:给一个大小为n的数组a[i]以及n各数,求所有f(le,ri)的和([le,ri]是[1,n]的所有子区间),f(le,ri)是指区间[le,ri]里每一个满足一定条件的a[i]的个数,

条件是区间[le,ri]里没有一个不等于i的j使得a[i]%a[j]=0;(如果le==ri,区间只有一个a[i],这个是满足条件的,因为确实是没有一个不等于i的j,那就更不用谈什么模了。)

思路:数据大,暴力无解,从a[i]%a[j]=0入手,这样的a[j]一定是a[i]的因子,也就是说一个区间一旦有了a[i]的因子a[i]对答案就没有贡献了,那么对于每一个a[i]
向两边扩张区间,遇到离a[i]最近的一个因子,存下位置le[i],ri[i],那么a[i]有用的最大区间就是[le[i],ri[i]],然后这个怎么算a[i]对答案的贡献,只要在这个区间包含到a[i]

的所有子区间都满足条件并且贡献答案1,那么就算包含a[i]的区间个数,既然包含a[i],那么子区间的起点le可以从le[i]取到i,终点从i取到ri[i],总共有(i-le[i])*(ri[i]-i)个;

这样还有个问题,如从i开始直接往两边去一个一个找端点还是会超时的,需要优化,a[i]只有10000,不大因子个数也不多,那么用筛法的思想对每个数把其位置添加到这个数的

倍数后面,以表示它的倍数有这个因子;

 

技术分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<string>
 4 #include<algorithm>
 5 #include<set>
 6 #include<map>
 7 #include<queue>
 8 #include<vector>
 9 #include<iterator>
10 #include<utility>
11 #include<sstream>
12 #include<iostream>
13 #include<cmath>
14 #include<stack>
15 using namespace std;
16 const int INF=1000000007;
17 const double eps=0.00000001;
18 const int maxn=1e5+5;
19 const int mod=1e9+7;
20 typedef __int64 ll;
21 typedef struct
22 {
23     int val,pos;
24 }aa;
25 aa a[maxn];
26 int l[maxn],r[maxn];
27 vector<int> v[10005];//保存每个数i的因子的在a[]数组里的下标
28 bool cmp(aa x,aa y)
29 {
30     if(x.val==y.val)//注意如果有相同的数,优先前面的,为了找到最近的因子
31         return x.pos<y.pos;
32     return x.val<y.val;
33 }
34 int main()
35 {
36     int n;
37     while(~scanf("%d",&n))
38     {
39         ll ans=0;
40         for(int i=1;i<=n;i++)
41             scanf("%d",&a[i].val),a[i].pos=i;
42         for(int i=1;i<=10005;i++) v[i].clear();
43         for(int i=1;i<=n;i++)
44             l[i]=0,r[i]=n+1;
45         //用结构体存了下标对应的数,排序是为找因子
46         //每个数的因子一定小于等于它,因子先出现放在前面;
47         //当考虑到一个数的时候,它的因子已经全部找出来了
48         sort(a,a+n,cmp);
49         for(int i=1;i<=n;i++)
50         {
51             int tmp=a[i].val;
52             for(int j=tmp;j<=10000;j+=tmp)//添加因子,数不多
53                 v[j].push_back(a[i].pos);
54         }
55         for(int i=1;i<=n;i++)
56         {
57             int tmp=a[i].val;
58             for(int j=v[tmp].size()-1;j>=0;j--)//暴搜所有因子的位置,找最近的
59             {
60                 if(v[tmp][j]<a[i].pos) l[a[i].pos]=max(l[a[i].pos],v[tmp][j]);
61                 if(v[tmp][j]>a[i].pos) r[a[i].pos]=min(r[a[i].pos],v[tmp][j]);
62             }
63         }
64         for(int i=1;i<=n;i++)
65         {
66             int t=a[i].pos;
67             ans=(ans+(ll)(a[i].pos-l[a[i].pos])*(r[a[i].pos]-a[i].pos))%mod;
68         }
69         printf("%I64d\n",ans);
70     }
71     return 0;
72 }
View Code

 

hdu 5288 OO’s Sequence

标签:

原文地址:http://www.cnblogs.com/2445512490wh/p/4675032.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!