zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 111 (Rated for Div. 2) D.Excellent Arrays 对称 数形结合

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

    题意

    数组(a)(good) 当且仅当(a_i eq 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 imes 10^5,-10^9 leq l leq 1,nleq 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 imes binom{n}{half}),奇数时(2lim imes binom{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)

    于是贡献( binom{R-L+1}{1-L+half})偶数,(2 binom{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 << '
    ';
    	}
    }
    
  • 相关阅读:
    27、驱动调试之修改系统时钟中断定位系统僵死问题
    25、驱动调试之打印到proc虚拟文件
    24、驱动调试之printk
    23、uevent/hotplug热拔插机制
    22、DMA驱动程序框架
    21、IIS声卡驱动程序
    20、RTC驱动程序
    ZOJ
    HDU-4272 LianLianKan (dfs)
    UVA-624 CD (01背包+路径记忆)
  • 原文地址:https://www.cnblogs.com/hznumqf/p/15024949.html
Copyright © 2011-2022 走看看