时限:1.5s 空间:128mb
给定一个n*m的矩阵,其中第i行j列的数字为i*j,给出q次询问,每次询问一个整数k,要求输出第k小的数字。
输入:第一行三个整数n,m,q
接下来q次询问,每次询问一个k。
输出:q行,每行1个整数表示第k小的数字。
对于100%的数据,1<=n,m<=1e9,q<=100,1<=k<=max(n,m)。
样例输入:
2 2 1
2
样例输出:
2
对于每一次询问,我们考虑二分,二分第k小的数字是多少,判断的时候就是判断小于等于这个数字的数字个数有多少个,既x/1+x/2+x/3+……x/x。这个式子可以在sqrt(n)的时间内求出。总复杂度qsqrt(n)logk。二分的上界取k本身即可,因为k<=max(n,m),即1-k肯定都是存在的,k这个数字的排名一定大于等于k。
1 #include<cstdio> 2 #include<algorithm> 3 #define ll long long 4 using namespace std; 5 ll n,m,q; 6 ll check(ll x){ 7 ll now=1,ans=0; 8 while(now<=x){ 9 ll tem1=x/now,tem2=x/tem1; 10 ans+=min(m,tem1)*(tem2-now+1); 11 now=tem2+1; 12 } 13 return ans; 14 } 15 int main() 16 { 17 scanf("%I64d%I64d%I64d",&n,&m,&q); 18 for(int i=1;i<=q;i++){ 19 ll l,r,x; 20 scanf("%I64d",&x); 21 l=1,r=x; 22 while(l!=r){ 23 ll mid=(l+r)>>1; 24 if(check(mid)<x)l=mid+1; 25 else r=mid; 26 } 27 printf("%I64d\n",l); 28 } 29 return 0; 30 }