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

——————悄悄地求點贊——————

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章