zoukankan      html  css  js  c++  java
  • [YY题]HDOJ5288 OO’s Sequence

    题意:求这个式子 $sum limits_{i=1}^{n} sum limits_{j=1}^{m} f(i, j) mod (10^9 + 7)$ 的值

    就是对每个区间[i, j]枚举区间中的每个数$a_i$到$a_j$, 判断这个$a$是否对[i, j]这个区间内所有数取模都不等于0, 若是,则这个区间满足条件

    问有多少个满足条件的区间

    比如案例是这样跑的

        int ans=0;
        for(int i=1;i<=5;i++)
            for(int j=i;j<=5;j++)
            {
                for(int k=i;k<=j;k++)   // 注意要枚举[i, j]中的每个数
                {
                    bool flag=0;
                    for(int l=i;l<=j;l++)
                        if(k!=l && k%l==0)
                            flag=1;
                    if(!flag)           // 对区间内所有数取模都不等于0 
                        ans++;
                }
            }

    跟省赛某题很像, 计算每个数a[i]对ans的贡献

    比如对于案例 1 2 3 4 5

    1这个数字对于答案的贡献是{1}, {1, 2}, {1, 2, 3}, {1, 2, 3, 4}, {1, 2, 3, 4, 5} 这5个区间

    2 这个数字对于答案的贡献是{2}, {2, 3}, {2, 3, 4}, {2, 3, 4, 5} 这4个区间   ( {1, 2}区间不满足,因为2%1==0 )

    ... ...

    来看4 这个数 

    它往左取区间 {4}, {3, 4} 当取到2的时候, 发现4%2==0了,那么就不必再往左了(对于连续的区间, 再往左则必定会经过2,那么该区间就不合法了)

    同理,可以想到往右取, 当找到一个数被它取模等于0, 那么就不必再往右了

    好了,现在对于一个数a[i], 它左边 到 不合法的数(被它取模等于0)为止 之间有x个数, 右边到不合法的数为止 有y个数

    那么a[i]这个数对答案的贡献就是(x+1)*(y+1)

    为什么呢?

    因为是连续的区间, 所以这个区间的左端点可以取a[i]左边0个数、1个数、2个数... ...x个数;右边0个数、1个数、2个数... ...y个数

    左边有(x+1)种取法,右边有(y+1)种, 相乘就是总取法数

    那么我们只要找到离a[i]最近的一左一右两个不合法数的位置$l$和$r$, 那么$(i-l)*(r-i)$ 就是a[i]的贡献($i-l-1$就是上面所讲的x)

    之后只要遍历每个a, 将每个a的贡献累加起来即是最后答案。

    那么现在问题就转化成了如何求一个 离它最近的 能被它整除的数 的位置

    我们是这样做的:

    开个数组将每个a[i]的倍数都记为i  (比如 a[0]=2, 那么就将2、4、6... ...10000 都记下0号位置;a[x]=y, 就将y、2y、3y... ... 都记下x位置)

    就跟筛因子一样   (因为1比较特殊,会退化到$n^2$, 因此特殊处理)   复杂度为O(NlogN)  (N为10000, 因为数最大为10000)

            for(int i=0;i<n;i++)
            {
                if(a[i]==1)
                    one.push_back(i);
                else
                    for(int j=a[i];j<=10000;j+=a[i])
                        b[j].push_back(i);
            }  

    因为是按顺序遍历了a数组, 所以记下的位置(比如2 2 3 6 12  对于12记下的是0 1 2 3 4 )一定是递增的

    那么就可以二分来寻找离$i$最近的位置

    p.s. lower_bound 找的是大于等于x的数位置

          upper_bound找的是大于x的数的位置

     1 const LL mod=1e9+7;
     2 int a[100005];
     3 vector<int> b[10005];
     4 vector<int> one;
     5 int read()
     6 {
     7     char ch=' ';
     8     int ans=0;
     9     while(ch<'0' || ch>'9')
    10         ch=getchar();
    11     while(ch<='9' && ch>='0')
    12     {
    13         ans=ans*10+ch-'0';
    14         ch=getchar();
    15     }
    16     return ans;
    17 }
    18 
    19 int main()
    20 {
    21 //    freopen("1001.in", "r", stdin);
    22 //    freopen("out.txt", "w", stdout);
    23     int n;
    24     while(~scanf("%d", &n))
    25     {
    26         for(int i=0;i<n;i++)a[i]=read();
    27 //            scanf("%d", &a[i]);
    28         for(int i=0;i<=10000;i++)
    29         {
    30             b[i].clear();
    31             b[i].push_back(-1);
    32         }
    33         one.clear();
    34         one.push_back(-1);
    35         for(int i=0;i<n;i++)
    36         {
    37             if(a[i]==1)
    38                 one.push_back(i);
    39             else
    40                 for(int j=a[i];j<=10000;j+=a[i])
    41                     b[j].push_back(i);
    42         }
    43         for(int i=0;i<=10000;i++)
    44             b[i].push_back(n);
    45         one.push_back(n);
    46         LL ans=0;
    47         for(int i=0;i<n;i++)
    48         {
    49             int p1=lower_bound(b[a[i]].begin(), b[a[i]].end(), i)-b[a[i]].begin()-1;
    50             int p2=lower_bound(one.begin(), one.end(), i)-one.begin()-1;
    51             int l=max(b[a[i]][p1], one[p2]);
    52             p1=upper_bound(b[a[i]].begin(), b[a[i]].end(), i)-b[a[i]].begin();
    53             p2=upper_bound(one.begin(), one.end(), i)-one.begin();
    54             int r=min(b[a[i]][p1], one[p2]);
    55 //            printf("%d %d
    ", l, r);
    56             ans=(ans+((i-l)*(r-i))%mod)%mod;
    57         }
    58         printf("%I64d
    ", ans%mod);
    59     }
    60     return 0;
    61 }
    HDOJ 5288
  • 相关阅读:
    pygame “音乐盒”---- 播放一首歌& 点击对话框后背景以及对话框大小改变
    虚拟机VMware里 windows server 2003 扩充C盘方法
    pygame简单动态图 & 动态图片的移动
    用C++ 自娱自乐
    Linux学习笔记----(2)
    Linux学习笔记--(1)
    JSON.stringify语法解析(自己留存)
    css 框架——base.css,作用是重设浏览器默认样式和提供通用原子类。自己留存
    div里嵌套了img底部会有白块问题和图片一像素问题解决
    全面解析Linux数字文件权限
  • 原文地址:https://www.cnblogs.com/Empress/p/4665979.html
Copyright © 2011-2022 走看看