Codeforces Round #619 (Div. 2) C.Ayoub's function

题目的意思是长度为n的01串,知道里面有m个1,为这个串中最多有多少个子串含有1
脑残的我都想到了插空,就是最后没打出来,==

想要含1的子串最多,可以先把1的序列写出来,之后向1序列的空中去插入0,
为什么?
因为均匀分布的1,可以使得长度大的子串中必定有1,对于长度小的子串也减少了1的重复使用。
还不懂?
例子:
n = 5,m = 2
样例中字符串是 : 01010,这样子所有长度>2的子串必定含有1,并且对于长度=2的子串,每个子串里面都只有1个1,减少浪费。
否则:01100,同样是对长度>2的子串都有1,但是11这个子串中有两个1,浪费(明明有一个1就行了)。导致最后长度为2子串有1的只有3个,样例可以有4个。
所以,均匀分布的1保证结果最大。
长度为n的串,子串数目为n*(n+1)/2,这个不需要证明吧
p:插空的时候,每个空里面放多少个0
当然存在插空的时候不能完全均匀地插0
r:在完全均匀地情况下,有多少个0多余
这r个0还要插到r个空中
所以,我们现在有r个p+1的0,m+1-r个p的0.

用所有的子串数目 - 全0的子串数目即可。(我脑残没想到)
全0的子串数目当然是用空中的0计算啊。

#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 50;
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
	{
		long long n,m;
		cin >> n >> m;
		long long z = n - m;
		long long ans = n*(n+1)/2;//所有子串 
		long long p = z / (m+1);//插空时,每个空插多少个0 
		long long r = z % (m+1);//多余的0 
		ans -= p*(p+1)/2*(m+1-r) + (p+1)*(p+2)/2*r;
		//也就是空中,有r个是p+1 0,m+1-r个是p 0
		//所有的子串 - 全0的子串 
		cout << ans << endl;
	}
	return 0; 
} 

——————悄悄地求点赞——————

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值