CodeForces - 1301C Ayoub's function(数学)

题目链接:点击查看

题目大意:规定函数 f(s) 为01字符串 s 中至少包含一个 1 的所有子串的数量,比如 f(10101) = 12 ,其中十二个子串分别为(1,2),(1,3),(1,4),(1,5),(2,2),(2,3),(2,4),(2,5),(3,4),(3,5),(4,4),(4,5),现在给出一个01字符串的长度为 n ,其中包含了 m 个 1 ,问所有情况中 f(s) 的最大值

题目分析:通过样例不难看出,如果想要使得 f(s) 最大,那么必须使得 0 的连续部分尽量多,而这个题正难则反,直接求至少包含 1 的子串比较难求,我们可以考虑用总的子串个数减去只含有 0 的子串个数,而对于一个字符串而言,其子串的个数为:1+2+3+...+n-1+n=(n+1)*n/2,而一个字符串中有 m 个 1 ,相应的可以将 (n-m) 个 0 分割为 (m+1) 个区间中,其中:

  1. 有 ( n - m ) % ( m + 1 ) 个区间中含有 ( n - m ) / ( m + 1 ) 个 0
  2. 有( m + 1 ) - [ ( n - m ) % ( m + 1 ) ] 个区间中含有 ( n - m ) / ( m + 1 ) + 1 个 0

然后直接计算就好了,上面的等式看似很复杂,但自己推一下其实也就那回事

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<unordered_map>
using namespace std;
    
typedef long long LL;
   
typedef unsigned long long ull;
    
const int inf=0x3f3f3f3f;
    
const int N=1e3+100;

LL C(LL n)
{
	return n*(n+1)/2;
}

int main()
{
//#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//    freopen("output.txt","w",stdout);
//#endif
//  ios::sync_with_stdio(false);
   	int w;
   	cin>>w;
   	while(w--)
   	{
   		LL n,m;
   		scanf("%lld%lld",&n,&m);
   		LL zero=n-m;//有这么多 0,共分成了 m+1 段
		LL t=zero/(m+1);//每段 0 含有 t 个 0 
		LL k2=zero%(m+1);//有k2段 0 含有 t+1 个 0  
		LL k1=(m+1)-k2;//有k1段 0 含有 t 个 0 
		printf("%lld\n",C(n)-C(t)*k1-C(t+1)*k2);
	}
    
    
    
    
     
     
       
       
       
       
       
       
       
    return 0;
}
发布了646 篇原创文章 · 获赞 20 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/104322981
今日推荐