代码源:673、Ayoub's function

163 阅读3分钟

本文已参与[新人创作礼]活动,一起开启掘金创作之路 logo.png

题目描述

这是4月6日代码源div1的每日一题。

Ayoub's function - 题目 - Daimayuan Online Judge

题目描述

定义函数 f(s) ,s为01字符串,f(s)为字符串s中至少包含一个1的子串数量

现在存在一字符串s,给出字符串长度 n ,和它包含的1的数量 m , 求最大的可能的 f(s)

输入格式

输入由多组测试数据组成

第一行输入一个整数 1≤T≤10^5 为数据组数

接下来 T 行,每行输入两个整数 n,m (1≤n≤10^9,0≤m≤n)

输出格式

输出 T 行,每行一个整数做为答案

输入样例

5
3 1
3 2
3 3
4 0
5 2

输出样例

4
5
6
0
12

样例解释

第一组数据中,s=010时,f(s)=4

第二组数据中,s=101时,f(s)=5

第三组数据中,s=111时,f(s)=6

第四组数据中,s=0000时,f(s)=0

第五组数据中,s=01010时,f(s)=12

问题解析

其实我们也能感觉到,当1分开放且尽量放在中间,能得到的f(s)最大,毕竟这样每个1能提供的贡献可以最大,比如长度为6,1个数为2,001010和000011和001100得到的f(s)分别是,16、7、15。其实也可以验证,当1分开放时,每个1可以提供的长度为2的串有01和10两种,这样两个1可以提供4个,但要是两个1挨在一起,那一共就是01、11和10三种,少了一种,放在边界也是一样的。

这里1分开的 距离越远且离边界的距离越远,他们可以单独提供的f(s)就越大。这样可以提高每个1的利用率,所以我们就把每个1等距的摆放即可。然后每个1能单独提供的子串数量取决于它们距离边界或其它1的距离,比如00100100,每个1可以单独提供2个长度为2和3个长度为3的字符串,我们先算它们能单独提供的f(s)是多少。然后再算其它1合在一起的f(s),两者加一起即可。其它1合在一起的f(s)也好算,当每个每个1能提供的长度算完后,后面的字符串长度每次都会有至少一个的1在里面,那么我们就枚举字符串的长度一直到n为止就行。当然一个个算是会超时的,但我们也能看出来,这两次计算f(s)都是一种等差数列的情况,我们可以用等差数列的前n项和来算,由于第一次的f(s)是计算每个1的单独贡献,所以是1的数量乘上每个1的贡献。

AC代码

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")

#define endl '\n';
typedef long long ll;
typedef pair<int, int> PII;
const int N = 4e5 + 50;

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t;
    cin >> t;
    while (t--)
    {
        ll n, m;
        cin >> n >> m;
        ll res = m;
        if (m == 0)
        {
            cout << 0 << endl;
            continue;
        }
        
        n -= m;
        ll ans = n / (m + 1) + 1;
        res += m * ((2 + ans) * (ans - 1) / 2);
        res += (1 + n - ans + m) * (n - ans + m) / 2;
        cout << res << endl;
        
    }
    return 0;
}