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; 
} 

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

发布了11 篇原创文章 · 获赞 0 · 访问量 599

猜你喜欢

转载自blog.csdn.net/weixin_43934344/article/details/104305440
今日推荐