C. Ayoub's function

题意:给出一个字符串中1的个数,和它的长度,其余都是0,然后构造一个字符串,使得f(s)最大,f(s)表示有多少个点对,
使得这个点对的区间中至少包含一个1。

分析:这题采用容斥原理,从正面构造最大点对数的字符串很困难,我们可以从反面思考,f(s) = 所有点对的数量 - 区间中不包含0的个数的点对数量,假设所有0挤在一起,那么它所能构造的点对数量是它的长度l * (l + 1) / 2,那么f(s) = n * (n + 1) / 2 - l * (l + 1) / 2,如何让l * (l + 1) / 2尽量小呢?可以发现这是一个二次函数,是随着连续0的长度地递增,函数值也飞快地递增地,我们可以让这些连续的0的个数分散开来,那么f(s)就越大,为了让0尽量分散开来,我们可以用1把它们分开来,题目中给出了有m个1,0的个数就是(n - m)个,有m个1,我们就可以隔开m + 1组0,平均分配,那么每组就有(n - m) / (m + 1)个0,然后还有余数我们尽量平均分在每个组中,那么就会产生(k + 1) * ((n - m) % (m + 1))

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
using LL = long long;
LL n, m;
int main()
{
    int t;
    scanf("%d", &t);

    while (t--)
    {
        cin >> n >> m;
        LL res = n * (n + 1) / 2;
        LL z = (n - m);//0的个数

        LL k = (n - m) / (m + 1);//每组0的个数

        LL r = (n - m) % (m + 1);

        res = res - k * (k + 1) / 2 * (m + 1) - (k + 1) * r;

        cout << res << endl;
    }



    return 0;
}


猜你喜欢

转载自www.cnblogs.com/pixel-Teee/p/12307107.html
今日推荐