ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Educational Codeforces Round 111 (Rated for Div. 2) D.Excellent Arrays 对称 数形结合

2021-07-17 21:31:26  阅读:168  来源: 互联网

标签:Educational Rated leq Arrays ll int ch fac MOD


Educational Codeforces Round 111 (Rated for Div. 2) D.Excellent Arrays 对称 数形结合

题意

数组\(a\)为\(good\) 当且仅当\(a_i \neq i\)

令\(F(a)\)表示数对\((i,j)\)满足\(a_i+a_j = i + j\)

定义数组\(a\)为\(excellent\)当且仅当:

1.\(a\)为good

2.\(l \leq a_i \leq r\) 对于任意\(i\)成立

3.\(F(a)\)是所有可能的good的数组中最大的

\[2 \leq n \leq 2\times 10^5,-10^9 \leq l \leq 1,n\leq r \leq 10^9 \]

分析

如果直接做会发现题目条件有点多,考虑对题目化简

注意到\(a_i + a_j = i + j\)这个式子有很强的对称性,一般可以移项以后构造出一些等式

此题可以令\(a_i = i + k_i\) 那么\(a_i + a_j = i + j\)即可转化为\(k_i + k_j = 0\)即\(k_i = k_j\),就会有一对满足条件的数对

那么相当于对每个\(a_i\)赋值一个\(k_i\),对于相同的数对我们希望它尽量多。画到坐标系里就是画两条分别代表\(a_i = i + k_i\)和\(a_i = i - k_i\)

这里取相反数就是对应前面的”条件“,每个\(k_i\)都对应了一种答案的取法

注意题目给的\(l,r\)范围很有意思,相当于在坐标系上画两个平行x轴的线来限定\(k\) ,限定等价于端点处的两个不等式\(1 - k \geq l,n + k \leq r\) 即有\(k \geq min(1 - l,r - n)\)

图上可以显示得看出来,在这个条件下任意\(a_i\)都可以赋\(+k_i\)或者\(-k_i\)(因为两个都满足了) 因此肯定是贪心的让数量均匀(基本不等式)

即贡献\(lim = min(1-l,r-n)\) ,偶数时\(lim \times \tbinom{n}{half}\),奇数时\(2lim \times \tbinom{n}{half}\)

再考虑\(k \leq lim\)的情况,这个时候画图,会发现两边的条件被限定了,即左边的部分由于斜线下移,交点右移,因此左边的不满足\(-k_i\)时的情况,只能选\(+k_i\),右边的同理

这个时候贡献就由\(k\)的偏移情况来决定,左交点\(L = max(1,l+k)\),右交点\(R = min(n,r-k)\)

此时确定了\(-k_i\) \(L - 1\)个,\(+k_i\) $n -R $个,这个时候中间还要选\(2x + n - L + R = R - L + 1\)即\(x = 1 - L + half\)个

于是贡献\(\tbinom{R-L+1}{1-L+half}\)偶数,\(2\tbinom{R-L+1}{1-L+half}\) 奇数

当然,这个时候只需要暴力枚举\(k\)就好了

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll rd(){
	ll x = 0;
	int f = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9') {
		if(ch == '-') f = -1;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9') {
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return x * f;
}

const int MOD = 1e9 + 7;

void add(int &x,int y){
	if(x + y >= MOD) x = x + y - MOD;
	else x += y;
}

int ksm(int a,int b = MOD - 2,int m = MOD){
	int ans = 1;
	int base = a;
	while(b){
		if(b & 1) ans = (ll)ans * base % MOD;
		base = (ll)base * base % MOD;
		b >>= 1;
	}
	return ans;
}

const int maxn = 2e5 + 5;

int fac[maxn],iv[maxn];

int C(int x,int y){
	if(y < 0 || x < y) return 0;
	return (ll)fac[x] * iv[x - y] % MOD * iv[y] % MOD;
}

int main(){
	fac[0] = 1;
	for(int i = 1;i < maxn;i++)
		fac[i]  = (ll)fac[i - 1] * i % MOD;
	for(int i = 0;i < maxn;i++)
		iv[i] = ksm(fac[i]);
	int T = rd();
	for(int t = 1;t <= T;t++){
		int n = rd();
		int l = rd();
		int r = rd();
		int ans = 0;
		int lim = min(1 - l,r - n);
		ans = (ll)lim * C(n,n / 2) % MOD;
		if(n & 1) add(ans,(ll)lim * C(n,n / 2) % MOD);
		for(int u = lim + 1;;u++){
			int L = max(1,l + u);
			int R = min(n,r - u);
			int rest = R + 1 - L;
			if(rest < 0) break;
			add(ans,C(rest,n / 2 - (L - 1)));
			if(n & 1)
				add(ans,C(rest,n / 2 + 1 - (L - 1)));
		}
		cout << ans << '\n';
	}
}

标签:Educational,Rated,leq,Arrays,ll,int,ch,fac,MOD
来源: https://www.cnblogs.com/hznumqf/p/15024949.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有