中兴2021批笔试题解

总结:人菜思维僵硬.jpg…做笔试感觉智商严重下降…以后得写点正常的AGC题之类的了…

T1

题目大意:给出长度为n的排列,要求按顺序插入排序二叉树,问经过根节点的最长路径长度。
n < = 1 e 5 n<=1e5

奇怪的做法:

把数组进行排序后,把id给拿出来。
例如 A i = [ 5 , 3 , 2 , 1 , 6 , 7 , 4 ] A_i=[5,3,2,1,6,7,4]
排序后得到 B i = [ 4 , 3 , 2 , 7 , 1 , 5 , 6 ] B_i=[4,3,2,7,1,5,6]
B i B_i 为第i小的数的id。那么分治进行处理, B i B_i 的左边的最小数即为左儿子,右边最小即为右儿子。

这个过程用ST表处理即可。时间复杂度 O ( n l o g n ) O(nlogn)

(虽然这看上去就很不正解,如果大家有更简单的做法可以评论区告诉我Orzzz…)

C++代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
struct data_p{int id,num;}pot[100005];
int n,f[100005][25],root;
double T,lenn;
bool cmp(data_p a,data_p b){return (a.num<b.num)||(a.num==b.num&&a.id<b.id);}
int fnd(int l,int r)
{
	if(l>r)return 0;
	double len=1.0*log(1.0*(r-l+1))/log(2.0);int rot;
	if(pot[f[l][int(len)]].id<pot[f[r-(1<<int(len))+1][int(len)]].id)rot=f[l][int(len)];
	else rot=f[r-(1<<int(len))+1][int(len)];
	return max(fnd(l,rot-1),fnd(rot+1,r))+1;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		pot[i].id=i;
		scanf("%d",&pot[i].num);
	}
	sort(pot+1,pot+n+1,cmp);
	T=1.0*log(1.0*n)/log(2.0);
	for(int i=1;i<=n;i++){f[i][0]=i;if(pot[i].id==1)root=i;}
	for(int i=1;i<=T;i++)
	{
		lenn=1<<i-1;
		for(int j=1;j<=n-lenn*2+1;j++)
		{
			if(pot[f[j][i-1]].id<pot[f[int(j+lenn)][i-1]].id)f[j][i]=f[j][i-1];
			else f[j][i]=f[int(j+lenn)][i-1];
		}
	}
	printf("%d",fnd(1,root-1)+fnd(root+1,n)+1);
	return 0;
}

T2

题目大意:n个男生,m个女生,选出k个人的方案数,要求至少选3个男生,2个女生。
n , m < = 1000 n,m<=1000

枚举选的男生数量,然后得到选女生的数量,直接组合数算一算即可…

C++代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1000005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;

inline int read()
{
	int x=0,w=1; char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
	return w==1?x:-x;
}

ll fac[maxn],inv[maxn],n,k;
const ll mod=1000000007;

inline ll pw(ll a,ll b)
{
	ll ans=1,base=a;
	while(b)
	{
		if(b&1) ans=(ans*base)%mod;
		base=(base*base)%mod; b>>=1;
	}
	return ans;
}

inline ll C(int N,int M){return (fac[N]*inv[M]%mod)*inv[N-M]%mod;}

int main()
{
	fac[0]=1; inv[0]=1;
	rep(i,1,(maxn-5)) fac[i]=(fac[i-1]*i)%mod;
	rep(i,1,(maxn-5)) inv[i]=pw(fac[i],mod-2);
	ll n,m,k,ans=0; cin>>n>>m>>k;
	for(int i=max(3ll,k-m);i<=n;i++)
	{
		int x=k-i; if(x<2) break;
		ans=(ans+(C(n,i)*C(m,x))%mod)%mod;
	}
	cout<<ans<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38649940/article/details/108422535
今日推荐