搜索 - hdu5288 OO’s Sequence

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=5288

题意:

给定序列,问对该序列的每个区间,有多少个数字满足,在该区间中,其他数字都不是该数字的因数

思路:

观察数字范围只有10^4,算出每个数字极左因数的位置,极右因数的位置,则该数字贡献为(R-X)(X-L),其中X为该数字在序列中的位置

预处理算出10^4内每个数字的因数,用ys向量存储;

做两次遍历,第一次从左向右,算出每个数字的极左因数位置,从左向右扫的过程用pos记录每个已计算的数字的位置;

第二次从右向左算极右因数位置

题目的ans超过int应用long long计算,同时,在计算中应先把(R-X)化成long long! 

代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;

const int MAXSIZE = 100000 + 5;
const int mod = 1e9+7;

vector<int> ys[10005];
int larr[MAXSIZE],rarr[MAXSIZE],arr[MAXSIZE];
int pos[MAXSIZE];

int main(){

    for (int i=1;i<=10000;++i){
        for (int j=i;j<=10000;j+=i){
            ys[j].push_back(i);
        }
    }

    int n;

    while (scanf("%d",&n)!=EOF){
        memset(arr,0,sizeof(arr));
        memset(larr,0,sizeof(larr));
        memset(rarr,0,sizeof(rarr));

        for (int i=1;i<=n;++i) scanf("%d",&arr[i]);
        memset(pos,0,sizeof(pos));
        for (int i=1;i<=n;++i){
            int t=0;
            for (int k=0;k<ys[i].size();++k){
                t=max(t,pos[ys[i][k]]);
            }
            larr[i]=t;
            pos[arr[i]]=i;
        }

        for (int i=1;i<=10000;++i) pos[i] = n+1;
        for (int i=n;i>=1;--i){
            int t=n+1;
            for (int k=0;k<ys[i].size();++k){
                t=min(t,pos[ys[i][k]]);
            }
            rarr[i] = t;
            pos[arr[i]]=i;
        }

        long long ans=0;
        for (int i=1;i<=n;++i){
            ans+=(long long)(rarr[i]-i)*(i-larr[i])%mod;
            ans%=mod;
            //cout<<"lr: "<<larr[i]<<" "<<rarr[i]<<endl;
        }
        cout<<ans<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值