zoukankan      html  css  js  c++  java
  • HDU 5288 OO’s Sequence

    题意:给一个序列,函数f(l, r)表示在[l, r]区间内有多少数字不是其他数字的倍数,求所有区间的f(l, r)之和。

    解法:第一次打多校……心里还有点小激动……然而一道签到题做了俩点……呜呜呜……今天的题还算简单……明天就更难了……写个题解纪念一下多校……

    对于序列中的每一个数,要找到从它的位置起向左右找最远连续不能被它整除的数的位置设为l和r,这个数的位置为pos,答案就是(pos - l + 1) * (r - pos + 1),只要分析一下样例就可以得到这个式子……然后为了找到l和r,先预处理出每个数的倍数,分别正序和倒序遍历序列,每次对标记用的数组更新倍数对应的因数位置,等遍历到这个倍数时就可以知道最近的因数位置了。

    代码:

    #include<stdio.h>
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<string.h>
    #include<math.h>
    #include<limits.h>
    #include<time.h>
    #include<stdlib.h>
    #include<map>
    #include<queue>
    #include<set>
    #include<stack>
    #include<vector>
    #define LL long long
    using namespace std;
    vector <int> v[10005];
    int num[100005];
    const int mod = 1e9 + 7;
    void init()
    {
        for(int i = 1; i < 10005; i++)
        {
            for(int j = 1; j * j <= i; j++)
            {
                if(i % j == 0)
                {
                    v[j].push_back(i);
                    if(j * j != i)
                        v[i / j].push_back(i);
                }
            }
        }
    }
    int s[10005], flag[10005];
    int minn1[100005], minn2[100005];
    int main()
    {
        int n;
        init();
        while(~scanf("%d", &n))
        {
            for(int i = 0; i < n; i++)
            {
                scanf("%d", &num[i]);
            }
            int ans = 0;
            for(int i = 0; i < n; i++)
            {
                minn1[i] = n - 1, minn2[i] = 0;
            }
            memset(s, 0, sizeof s);
            memset(flag, 0, sizeof flag);
            for(int i = 0; i < n; i++)
            {
                int len = v[num[i]].size();
                minn1[i] = s[num[i]];
                if(flag[num[i]])
                    minn1[i]++;
                for(int j = 0; j < len; j++)
                {
                    flag[v[num[i]][j]] = 1;
                    s[v[num[i]][j]] = i;
                }
            }
            for(int i = 0; i < 10005; i++)
                s[i] = n - 1;
            memset(flag, 0, sizeof flag);
            for(int i = n - 1; i >= 0; i--)
            {
                int len = v[num[i]].size();
                minn2[i] = s[num[i]];
                if(flag[num[i]])
                    minn2[i]--;
                for(int j = 0; j < len; j++)
                {
                    flag[v[num[i]][j]] = 1;
                    s[v[num[i]][j]] = i;
                }
            }
            for(int i = 0; i < n; i++)
            {
                ans += (i - minn1[i] + 1) * (minn2[i] - i + 1) % mod;
                if(ans > mod)
                    ans -= mod;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    查看用户密码
    OPM批次成本后台表
    查询物料事务处理历史记录脚本
    接收会计事件表和接收会计分录表
    为应付发票批添加ORG_ID
    项目环境配置剩余部分
    配置IDEA的基本设置操作
    NB: JAVA_HOME should point to a JDK not a JRE
    Windows10下的JAVA运行环境搭建 ——第一天
    python中的可变与不可变对象的区别
  • 原文地址:https://www.cnblogs.com/Apro/p/4666008.html
Copyright © 2011-2022 走看看