hdu5288 vector用法+ ……(多校1.1)

来源:互联网 发布:ubuntu 支持中文 编辑:程序博客网 时间:2024/06/05 00:49

题目大意:给定一个序列含有n个数,定义f(l,r) = l  ~r序列中没有因子的数的个数 ,求n个数的序列中所有的连续子序列的f和。对1000000007取模

思路:定义数组l , r .l[i] , r[i] 分别表示第i个元素左边最近因子的位置和右边最近的因子的位置。则第i个数贡献的f值为(i - l[i]) * (r[i] - i )。

在求l 和r的过程中,肯定不能每个因子都去遍历着找,必然会超时。首先,一个数a的因子必然在sqrt(a)内能找到,所以只需要枚举从sqrt(a)到1所有的因子,找到最近的一个l和r

即可。然后就是如何尽快的找到因子所在的位置,刚才说了,肯定不能去遍历,不然必然超时,如何用元素来确定他的下标?就想到了STL里面的vector,可以开10000个vector,

就定义为vector<int > v[10000],然后输入a[i]时。只需要v[a[i]].push_back(i)即可,然后查找的时候遍历即可,其实和hash思想差不多。

另外强调一点,x是y的因子,则y/x也是y的因子,y/x比一定小于sqrt(y)!!

#include <iostream>#include <cstdio>#include <string>#include <cstring>#include <fstream>#include <algorithm>#include <cmath>#include <queue>#include <stack>#include <vector>#include <map>#include <set>#include <iomanip>using namespace std;#define MAXN 100005#define MOD 1000000007int a[MAXN] , l[MAXN] , r[MAXN];int load[10005];vector<int> v[10005];vector<int>::iterator it;int n;void slove(int pos){    int num = (int)sqrt(a[pos]);    if(num * num != a[pos]) num ++;    int maxl = 0;    int minr = n + 1;    for(int i = num  ; i > 0 ; i --)    {        if(a[pos] % i != 0) continue;   //若不是因子,直接下一个        int res = a[pos] / i;       //是因子 , 则要找到他的另一个因子,一起判断        for(int j = 0; j < v[i].size() ; j ++ )        {            if(v[i][j] < pos) maxl = max (maxl , v[i][j]);            if(v[i][j] > pos) minr = min (minr , v[i][j]);        }        for(int j = 0; j < v[res].size() ; j ++ )        {            if(v[res][j] < pos) maxl = max (maxl , v[res][j]);            if(v[res][j] > pos) minr = min (minr , v[res][j]);        }    }    l[pos] = maxl;    r[pos] = minr;    return ;}int main(){    while(scanf("%d" , &n) != EOF)    {        memset(l , 0 , sizeof(l));        memset(r , 0 , sizeof(r));        for(int i = 1 ; i <= 10000 ; i ++ ) v[i].clear();        for(int i = 1 ; i <= n ; i ++ )        {            scanf("%d" , &a[i]);            v[a[i]].push_back(i);       //记录每个数字的位置        }        for(int i = 1 ; i <= n ; i ++ )        {            slove(i);      //找到l,r        }        int sum = 0;        for(int i = 1 ; i <= n ; i ++ )        {            sum = (sum + (i - l[i])*(r[i] - i) % MOD ) % MOD;        }        cout << sum << endl;    }    return 0;}



0 0
原创粉丝点击