CF1992G 题解

纪念一下独立做出来的 *2000。

题意简述

给你一个集合 A,其中的元素为 1,2,3,,n,定义 mex{B,k} 为集合 B 中从小到大不存在的第 k正整数

SAmex{S,|S|+1}

解法

考虑枚举 a,再计算有多少个 S 符合 mex{S,|S|+1}=a

我们分为两种情况:

  1. an,此时 S 中的元素可能小于 a,也可能大于 a

  2. n+1a2n+1,此时 S 中的元素小于 n

先考虑第一种情况。

既然是明摆着让 O(n2) 过,不如往 O(n2) 方面想想。

我们枚举 a 的同时枚举 S 中小于 a 的数的个数,记为 x,设 S 中大于 a 的数的个数为 y,则根据定义可以推导出 y=a12x

相当于在小于 aa1 个数中选择 x 个,在大于 ana 个数中选择 y 个,显然有 (a1x)(nay) 种情况,对应到答案的贡献就是 (a1x)(nay)×a

再考虑第二种情况。

也是枚举 a。设 x 为选择了多少个数(因为 x>n,所有的数小于等于 n,所以讨论 ax 的大小关系没意义),则容易发现,当且仅当 a=2x+1 时满足条件。

于是预处理组合数就可以在 O(n2) 的时间内回答一个测试点。

Code

#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int,int> pii;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
const int N=5e3+10,INF=0x3f3f3f3f3f3f3f3f,mod=1e9+7;
int jc[N],jcinv[N];
int qpow(int a,int p){
	int ans=1;
	while(p){
		if(p&1)ans=ans*a%mod;
		a=a*a%mod;
		p>>=1;
	}
	return ans;
}
void init(){
	jc[0]=jcinv[0]=1;
	for(int i=1;i<N;i++){
		jc[i]=jc[i-1]*i%mod;
		jcinv[i]=qpow(jc[i],mod-2);
	}
}
int C(int n,int m){return jc[n]*jcinv[n-m]%mod*jcinv[m]%mod;}
void solve(){
	int n,ans=0;
	cin>>n;
	for(int a=1;a<=n;a++){
		for(int x=0;x<=a-1;x++){
			int y=a-1-2*x;
			if(y<0)break;
			if(n-a>=y)ans=(ans+C(a-1,x)*C(n-a,y)%mod*a%mod)%mod;
		}
	}
	for(int a=n+1;a<=n+n+1;a++){
		if(a%2==1)ans=(ans+C(n,a/2)*a%mod)%mod;
	}
	cout<<ans<<'\n';
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	init();
	int t;cin>>t;
	while(t--)solve();
	return 0;
}
posted @   Linge_Zzzz  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示