HDU5288 OO’s Sequence

来源:互联网 发布:中国产业结构优化升级 编辑:程序博客网 时间:2024/05/03 11:41

多校第一场就爆零了,蛤蛤蛤蛤蛤。。。。

题目大意:给一个数组a,f(i,j)表示ai到aj之间存在(这样的数)的个数,(这样的数)就是它不可以整除这个区间内其他的数,求数组a的所有的区间[i,j](这样的数)的个数之和。

思路:对ai,找到ai左边离它最近的和右边离它最近的可以被它整除的数,并用l[i],r[i]记录它们的位置,那么在包含ai的集合中,ai是(这样的数)的次数ans[i]=(i-l[i])*(r[i]-i),然后把所有的ans[i]加起来即为结果,比赛的时候已经想到了这一步,然而并没有什么卵用。l[i]和r[i]的求法具体看代码注释。

#define _CRT_SECURE_NO_DEPRECATE#include<iostream>#include<cstdio>#include<algorithm>#include<string>#include<cstring>#include<queue>#include<vector>#include<cmath>#include<ctime>#define mx 100005#define LL long long #define mod 1000000007#define esp 1e-6#define y1 y1234#define INF 0x3f3f3f3f#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define maxn 200005const double PI = acos(-1.0);using namespace std;int n, a[mx];int l[mx], r[mx];int pre[mx];        //pre[k]表示k在数组中的位置vector<int>f[mx];   //f[k]记录k的因数void init(){for (int i = 1; i < 10001; i++){for (int j = i; j < 10001; j += i){f[j].push_back(i);} }return;}int main(){    init();while (scanf("%d", &n) != EOF){memset(pre, -1, sizeof pre);for (int i = 1; i <= n; i++){      //正向扫描数组l[i]scanf("%d", &a[i]);int ma = 0;for (int j = 0; j < f[a[i]].size(); ++j){     //遍历a[i]的所有因数int v = f[a[i]][j];if (pre[v] != -1)            //如果a[i]的因数v出现在数组a中ma = max(ma, pre[v]);    //比较上一个出现在数组a中的因数和v哪个离a[i]比较近,更新ma}l[i] = ma;                 pre[a[i]] = i;                   //更新pre数组}memset(pre, -1, sizeof pre);for (int i = n; i >= 1; i--){       //同理反向扫描数组求r[i]int mi = n + 1;for (int j = 0; j < f[a[i]].size(); ++j){int v = f[a[i]][j];if (pre[v] != -1)mi = min(mi, pre[v]);}r[i] = mi;pre[a[i]] = i;}LL ans = 0;for (int i = 1; i <= n; i++){LL x = i - l[i];LL y = r[i] - i;ans = ans + (x*y) % mod;}cout << ans%mod << endl;}return 0;}



0 0
原创粉丝点击