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

xiaoxiao2021-02-28  85

调和序列(“盛大游戏杯”第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] ); } } }
转载请注明原文地址: https://www.6miu.com/read-29787.html

最新回复(0)