Excellent Arrays

Excellent Arrays

思路:
(1)由 a i + a j = i + j a_i+a_j=i+j ai+aj=i+j a i a_i ai与下标 i i i有关,可以令 a i = i + k i a_i=i+k_i ai=i+ki代入上式将 i i i j j j消掉得到 k i = − k j k_i=-k_j ki=kj的关系。为了使满足 a i + a j = i + j a_i+a_j=i+j ai+aj=i+j的对数尽可能的多,可以使有一部分的值都为 k k k,另一部分的值都为 − k -k k。易知当一半为 k k k一半为 − k -k k F ( a ) F(a) F(a)的值最大。
(2)观察一下发现 k k k的取值不同, a i a_i ai可能只能 + k +k +k − k -k k或都行,一开始想固定 i i i的位置来确定 k k k的范围,后来发现不太行
(3)固定 k k k来判断其他,如果 k < = m i n ( r − n , 1 − l ) k<=min(r-n,1-l) k<=min(rn,1l)每个 a i a_i ai都能 + k +k +k − k -k k否则有的只能 + k +k +k − k -k k,遍历 k k k不超过 O ( n ) O(n) O(n)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
const ll mod = 1e9+7;
ll f[N],inv[N];
ll qp(ll a, ll b) {
    ll ret = 1;
    while (b) {
        if (b & 1)
            ret = ret * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ret;
}
void init(){
	f[1] = 1;
	inv[1] = 1;
	f[0] = 1;
	inv[0] = 1;
	for(int i = 2;i<N-5;i++){
		f[i] = f[i-1]*i%mod;
		inv[i] = inv[i-1]*qp(i,mod-2)%mod;
	}
}
ll C(ll n,ll k){
	if(k<0||n<k) return 0;
	return f[n]*inv[n-k]%mod*inv[k]%mod;
}
int main(){
	init();
	ll t,n,l,r;
	cin >> t;
	while(t--){
		cin >> n >> l >> r;
		ll a = n/2,b = n-n/2;
		ll ans = 0;
		ll st = min(r-n,1-l);
		ans += st*C(n,a)%mod;
		if(n&1){
			ans = (ans + st*C(n,b)%mod)%mod;
		}//如果n是奇数,那么k可能有a个也可能有b个 
		ll L = 1,R = n;//闭区间,这个数还不确定是+k还是-k 
		while(1){
			st++;
			if(R+st>r)R--;
			if(L-st<l)L++;
			if((L>b+1)||(R<=a-1)) break;
			ans = (ans+C(R-L+1,a-L+1))%mod;
			if(n&1) ans = (ans+C(R-L+1,b-L+1))%mod;
		}
		cout << ans << endl;
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值