[codeforces 1301C] Ayoub's function 容斥原理+隔板法+等差数列求和

Codeforces Round #619 (Div. 2)

[codeforces 1301C] Ayoub's function 容斥原理+隔板法+等差数列求和

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址https://codeforces.com/contest/1301/problem/C

Problem Lang Verdict Time Memory
C - Ayoub's function GNU C++11 Accepted 93 ms 0 KB

codeforces比赛时,第一次提交,无法AC,不要紧。此时建议:

1重读题目,看看是否有遗漏;

2举一些极端例子,验证自己的算法;

3重读代码,看看有无手误。

第二次,提交AC的可能性大增。

第二次提交,无法AC,可以考虑继续下一题。

该题算法核心,挨在一起的0尽可能少。

模拟了样例,找到了点感觉,继续尝试如下

00000
0

11111
5+4+3+2+1=(1+5)*5/2=15

001000
111111全集(1+6)*6/2=21
00数量(1+2)*2/2=3
000数量(1+3)*3/2=6
答案21-3-6=12容斥原理

n=5,m=0,1,2,3,4,5
00000
00100
01010
01101
01110
01111
11111

0|0|0|0|0
相邻之间可放的隔板,如上
隔板数量小于等于1的数量,那么0都是一个一个孤立的。

隔板数量大于1的数量,那么要让0的分布尽量均匀。举例如下
10 2
0001000100
0的数量8,1的数量2(可将0分成(2+1)=3块)
8/(2+1)=2,8%(2+1)=2再将余数2按1个1个的分到块中
00100100    (00)
0001000100  加入多余的0
计算过程如下
1111111111全集(1+10)*10/2=55
000数量(1+3)*3/2=6
000数量(1+3)*3/2=6
00数量(1+2)*2/2=3
答案55-6-6-3=40容斥原理

AC代码如下

#include <stdio.h>
#define LL long long
int main(){
	int t,i;
	LL n,m,cnt0,ans,a,b;
	scanf("%d",&t);
	while(t--){
		scanf("%lld%lld",&n,&m);
		cnt0=n-m,ans=0;
		if(m==0)printf("0\n");
		else if(cnt0-1<=m){
			ans+=(n+1)*n/2;
			ans-=cnt0;
			printf("%lld\n",ans);
		}else{//cnt0-1>m
			ans+=(n+1)*n/2;
			a=cnt0/(m+1),b=cnt0%(m+1);
			for(i=1;i<=b;i++)ans-=(a+1+1)*(a+1)/2;
			for(i=b+1;i<=m+1;i++)ans-=(a+1)*a/2;
			printf("%lld\n",ans);
		}
	}
	return 0;
}
发布了537 篇原创文章 · 获赞 529 · 访问量 44万+

猜你喜欢

转载自blog.csdn.net/mrcrack/article/details/104307721
今日推荐