hdu 5288 OO’s Sequence 2015 Multi-University Training Contest 1

本文介绍了一种方法,用于计算数组中每个区间的满足特定数学条件的数字个数,并将这些个数进行累加。通过枚举每个位置并查找其左右边界,利用预处理的因数信息来优化计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

OO’s Sequence

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 83    Accepted Submission(s): 34


Problem Description
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 a i mod a j=0,now OO want to know
i=1nj=inf(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 a i(0<a i<=10000)
 

Output
For each tests: ouput a line contain a number ans.
 

Sample Input
  
5 1 2 3 4 5
 

Sample Output
  
23
 

Source



求一个每个区间中,满足其他数字%该数字 != 0的数字个数,把每个区间满足条件的个数相加

方法:

枚举每个位置,求包含这个数字的区间个数,做加法。

对于ai,看ai左边最近的位置l,al是ai的因数,右边位置r,ar是ai的因数。那么满足的个数就是

(i-l)*(r-i)

预处理所有1-10000的因数。

从左到右,用pre[i]表示数字i出现的i的最右边的位置。算出每个位置的l。

同理从右到左,算出每个位置的r。







#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;


#define maxn 100007
vector<int> head[10007];
int pre[10007];
int num[maxn];

int lef[maxn];
int righ[maxn];

int main(){
    int n;
    for(int i = 1;i <= 10000;i++){
        head[i].clear();
        for(int j = 1;j*j<=i;j++){
            if(i%j == 0){
                head[i].push_back(j);
                head[i].push_back(i/j);
            }
        }
    }
    while(scanf("%d",&n)!=EOF){
        for(int i = 1;i <= n; i++)
            scanf("%d",&num[i]);
        memset(pre,0,sizeof(pre));
        for(int i = 1;i <= n; i++){
            int u = num[i];
            int p = 0;
            for(int j = 0;j < head[u].size(); j++)
                p = max(p,pre[head[u][j]]);
            lef[i] = p;
            pre[u] = i;
        }

        memset(pre,0x3f,sizeof(pre));
        for(int i = n; i > 0; i--){
            int u = num[i];
            int p = n+1;
            for(int j = 0;j < head[u].size();j++)
                p = min(p,pre[head[u][j]]);
            righ[i] = p;
            pre[u] = i;
        }
        long long ans = 0,l,r;
        long long mod = 1000000007;
        for(int i = 1; i <= n; i++){
            ans += (long long)(i-lef[i])*(righ[i]-i);
            ans %= mod;
        }
        cout<<ans<<endl;
    }
    return 0;
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GDRetop

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值