JZOJ-senior-5434. 【NOIP2017提高A组集训10.30】Matrix

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HuangXinyue1017/article/details/81407846

Time Limits: 1000 ms Memory Limits: 131072 KB

Description

这里写图片描述

Input

这里写图片描述

Output

这里写图片描述

Sample Input

3 5 3
1
3
5

Sample Output

1
2
3

Data Constraint

这里写图片描述

Solution

不难发现最优答案 0 < a n s < m a x ( N , M )

我们二分答案 m i d ,发现这个 m i d 在此矩阵中排序(从小到大)后的最右位置为 s = Σ i = 1 N m i d / i

其实就是将小于等于 m i d 的数的个数相加,这个要是不知道为什么的画个图看一看就好了

但是这样的复杂度为 O ( N l o g N ) ,显然会超时80分,那就继续优化

观察发现,上式 m i d / i 中有很多值是相同的,而且是连续一段一段的,其值的数量又不超过 N

于是我们想到经典解法——分块

我们跳着一段一段加答案,每次 i 跳到 m i d / ( m i d / i ) ,然后整个区间统计

时间复杂度 O ( l o g N N )

Code

#include<algorithm>
#include<cstdio>
#define ll long long

using namespace std;

int n,m,q,k;

bool ok(int x)
{
    ll s=0;
    for(int i=1,p;i<=min(n,x);i=p+1)
    {
        p=x/(x/i);
        s+=(ll)(p-i+1)*(x/i);
    }
    return s>=k;
}

int main()
{
    freopen("matrix.in","r",stdin);
    freopen("matrix.out","w",stdout);
    scanf("%d%d%d",&n,&m,&q);
    while(q--)
    {
        scanf("%d",&k);
        int l=1,r=k;
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(ok(mid)) r=mid;
                else l=mid+1;
        }
        printf("%d\n",l);
    }
}

猜你喜欢

转载自blog.csdn.net/HuangXinyue1017/article/details/81407846