傻逼服务器 调和序数 xjb暴力 数学

调和序列(“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛(重现赛))

发布时间: 2017年7月9日 20:20 时间限制: 1000ms 内存限制: 128M

描述

给定一个长度为n 的非负整数序列,下标为0 ,1 ,…,n−1 .

定义:sequence(K) : 由下标为K 的倍数组成的子序列,即下标为0 ,K ,2K ,…,[n−1/k]∗k

query(K,S) : 询问sequence(K) 中的第S 大的数字

输入
第一行一个整数T ,表示测试组数。
对于每组数据,第一行输入两个整数n ,m ,1<=n<=20000 , 1<=m<=100000 ,n 表示序列的长度,m 表示询问个数。
接下来一行是n 个整数a 0 ,a 1 ,..,a n−1 ,0<=a i <2 31 , i=0,1,…,n−1 ,表示序列。
接下来m 行,每行两个整数K,S
0 < K <= 10 9 , 1<=S<=n

输出
每组数据对于每个询问输出一行,若sequence(K) 的元素个数小于S ,输出−1 ;否则输出query(K,S)

样例输入1 复制 1
5 2
2 5 3 4 1
2 4
2 1

样例输出1 -1
3

很早就有数学家研究,比如中世纪后期的数学家Oresme在1360年就证明了这个级数是发散的.他的方法很简单:   1 +1/2+1/3 +1/4 + 1/5+ 1/6+1/7+1/8 +…   1/2+1/2+(1/4+1/4)+(1/8+1/8+1/8+1/8)+…   注意后一个级数每一项对应的分数都小于调和级数中每一项,而且后面级数的括号中的数值和都为1/2,这样的1/2有无穷多个,所以后一个级数是趋向无穷大的,进而调和级数也是发散的.   从更广泛的意义上讲,如果An是不全部为0的等差数列,则1/An就称为调和数列,求和所得即为调和级数,易得,所有调和级数都是发散于无穷的.
编辑本段推导
  随后很长一段时间,人们无法使用公式去逼近调和级数,直到无穷级数理论逐步成熟.1665年牛顿在他的著名著作《流数法》中推导出第一个幂级数:   ln(1+x) = x - x^2/2 + x^3/3 - …   Euler(欧拉)在1734年,利用Newton的成果,首先获得了调和级数有限多项和的值.结果是: 相关书籍
  1+1/2+1/3+1/4+…+1/n= ln(n+1)+r(r为常量)   他的证明是这样的:   根据Newton的幂级数有:   ln(1+1/x) = 1/x - 1/2x^2 + 1/3x^3 - …   于是:   1/x = ln((x+1)/x) + 1/2x^2 - 1/3x^3 + …   代入x=1,2,…,n,就给出:   1/1 = ln(2) + 1/2 - 1/3 + 1/4 -1/5 + …   1/2 = ln(3/2) + 1/2*4 - 1/3*8 + 1/4*16 - …   .   1/n = ln((n+1)/n) + 1/2n^2 - 1/3n^3 + …   相加,就得到:   1+1/2+1/3+1/4+…1/n = ln(n+1) + 1/2*(1+1/4+1/9+…+1/n^2) - 1/3*(1+1/8+1/27+…+1/n^3) + .   后面那一串和都是收敛的,我们可以定义   1+1/2+1/3+1/4+…1/n = ln(n+1) + r   Euler近似地计算了r的值,约为0.5772156649.这个数字就是后来称作的欧拉常数.不过遗憾的是,我们对这个常量还知之甚少,连这个数是有理数还是无理数都还是个谜.

简单的说最后的复杂度是一个比log 大一点的 log 所以总复杂度就是 n log log,然后就是一些边界了,傻瓜暴力

#include <bits/stdc++.h>
using namespace std;
vector<int> v[20010];
int num[20010];
bool comp(const int &a,const int &b)
{
    return a>b;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&num[i]);    
            v[i].clear();   
        }
        for(int i=1;i<n;i++)
        {
            for(int j=0;j<=(n-1)/i;j++)
            {
                v[i].push_back(num[j*i]);
            }
            sort(v[i].begin(),v[i].end(),comp);
        }
        while(m--)
        {
            int k,s;
            scanf("%d%d",&k,&s);
            if(k>=n)
            {
            if(s==1)
             printf("%d\n",num[0] );
            else
                printf("-1\n");
            continue;
            }
            if(v[k].size()<s) printf("-1\n");
            else
            printf("%d\n",v[k][s-1] );
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值