zoukankan      html  css  js  c++  java
  • hdu 5228 OO’s Sequence(单独取数算贡献)

    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 ai mod aj=0,now OO want to know
     
     
    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 ai(0<ai<=10000)
     
    Output
    For each tests: ouput a line contain a number ans.
     
    Sample Input
    
    
    5
    1 2 3 4 5
     
    Sample Output
    
    
    23
     
    题意:给你n个数,让你找出各个区间内不被任何a[j]整除的i的个数,并输出所有区间的个数和。
    举个栗子,样例数据就是
    f(1,1)f(1,2)f(1,3)f(1,4)f(1,5)
    f(2,2)f(2,3)f(2,4)f(2,5)
    f(3,3)f(3,4)f(3,5)
    f(4,4)f(4,5)
    f(5,5)
    这些区间内的不被任何a[j]整除的个数
    因为题目a[i]%a[j]==0,i!=j,
    所以f(1,1) 里面有一个 1,因为i!=j;
    f(1,2) 里面有一个1,因为2%1==0
    以此类推 f(1,3) f(1,4) f(1,5) 都是 1
    f(2,2) 一个
    f(2,3) 两个 2 和 3 因为有两个数i可以不等于j
    以此类推相信题意已经懂了
    当初我就是被题意杀了,还狂做三小时,一丝悲凉>_<
     
    思路:既然他给的是求每个数不被其他的数整除的区间个数,说明这个区间里面肯定包含a[i]
    然后我们把每个数所包含的区间全部弄出来,当然要符合条件没有可以整除a[i]的数的区间,就是大佬们讲的求每个数的贡献,看他贡献几个区间,包含这个数的区间他能贡献出来几个
    重点!!我们找a[i]左边的最近的可以整除a[i]的数的位置,再找右边的
    举个栗子,比如 1 3 4 2 3 1
    我们当前在枚举中间那个2
    左边我们找到了位置1的1,右边找到了位置6的1
    现在一个公式 (i-left)*(right-i) 就是该区间内所有区间种数,并且没有可以整除a[j]的数
    意思就是1 3 4 2 3 1  因为两边都是最近的可以整出的,所以中间肯定都是满足要求的,然后这个公式懂了意思自己也能推出来,不过特别要注意 2 2这个区间,所以公式里面两边都包含了中间这个2
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #include<queue>
    #include<vector>
    #include<map>
    #define MOD 1000000007
    using namespace std;
    int a[100001];
    int l[100001];//记录每个数的左边最接近得可整除的数的位置
    int r[100001];//记录每个数的右边最接近得可整除的数的位置
    int mp[100001];//记录之前出现过的数,判断是否是整除的数的标记数组,存的是那个数的位置
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF)
        {    
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
            }
            memset(mp,0,sizeof(mp));
            for(int i=1;i<=n;i++)//找左边最接近的数
            {
                l[i]=0;
                for(int j=1;j*j<=a[i];j++)//判断这个数是否被整除,取到根号就好
                {
                    if(a[i]%j==0)
                    {
                        if(mp[j]) l[i]=max(mp[j],l[i]);
                        if(mp[a[i]/j]) l[i]=max(mp[a[i]/j],l[i]);//这个是以根号为界限的右边的因子数,自己推导一下
                    }
                }
                mp[a[i]]=i;//出现过的数记录一下
            }
            memset(mp,0,sizeof(mp));
            for(int i=n;i>=1;i--)找右边最接近的数
            {
                r[i]=n+1;
                for(int j=1;j*j<=a[i];j++)
                {
                    if(a[i]%j==0)
                    {
                        if(mp[j]) r[i]=min(mp[j],r[i]);
                        if(mp[a[i]/j]) r[i]=min(mp[a[i]/j],r[i]);
                    }
                }
                mp[a[i]]=i;        
            }
            long long sum=0;
            for(int i=1;i<=n;i++)
            {
                sum+=(i-l[i])*(r[i]-i);//公式算每个数的贡献区间个数多少
            }
            printf("%lld
    ",sum%MOD);
        }
    }

    我个人觉得比赛的时候要有能力分清这个是否是一个求贡献的题目,下面讲下个人理解,我觉得如果一件事必须要这个成员参与

    ,而且有很多这类的的事,并且题目是要求每个个数之和之类的就是求贡献题

    也是个人一些推断,希望对你们有用,

    下面最后说一句,搞acm的小菜鸡绝不服输>_<`

  • 相关阅读:
    wex5 实战 框架拓展之2 事件派发与data刷新
    wex5 实战 框架拓展之1 公共data组件(Data)
    wex5 实战 HeidiSQL 导入Excel数据
    wex5 实战 手指触屏插件 hammer的集成与优劣
    wex5 实战 登陆帐号更换与用户id一致性
    wex5 实战 用户点评与提交设计技巧
    wex5 实战 省市县三级联动与地址薄同步
    wex5 实战 wex5与js的组件关系与执行顺序(父子与先后)
    wex5 实战 单页模式下的多页面数据同步
    [BZOJ]4237: 稻草人
  • 原文地址:https://www.cnblogs.com/Lis-/p/9311520.html
Copyright © 2011-2022 走看看