ICode9

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

某古 11 月月赛 I 游记

2020-10-31 19:33:58  阅读:158  来源: 互联网

标签:11 ... ch int sum choose 某古 游记 include


某古 11 月月赛 I 游记

难度好评,没有像我上次打的那场比赛那么水了,不过自己的分数还是好低,只会前三题。。。

希望你古月赛的题目一直都能像这场这么有意思。

A 「MCOI-03」正方

题目分析

三角形面积公式 \(S=\frac{1}{2}ah\) ,由于 \(a\) 相等,所以题目给出的其实就是 \(h\) 之比。

题目中给出了 \(a,b,c,d\) ,不妨令 \(a\le b\le c\le d\) ,由于题目给出的是正方形,所以必须要满足 \(a+d=b+c\) ,否则不是正方形,答案就是 \(0\) ,如果满足 \(a+d=b+c\) ,不妨令正方形的左下角为 \((0,0)\) ,正方形边长为 \(a+d\) ,那么这个点的选择方法就只有 \((a,b),(a,c),(b,a),(c,a),(d,b),(d,c),(b,d),(c,d)\) 八种,排序后去重就行了。

参考代码

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ch() getchar()
#define pc(x) putchar(x)
template<typename T>inline void read(T&x){
	int f;char c;
	for(f=1,c=ch();c<'0'||c>'9';c=ch())if(c=='-')f=-f;
	for(x=0;c<='9'&&c>='0';c=ch())x=x*10+(c&15);x*=f;
}
template<typename T>inline void write(T x){
	static char q[64];int cnt=0;
	if(!x)pc('0');if(x<0)pc('-'),x=-x;
	while(x)q[cnt++]=x%10+'0',x/=10;
	while(cnt--)pc(q[cnt]);
}
long long A[4];
pair<long long,long long>s[8];
int main(){
	int q;read(q);
	while(q--){
		for(int i=0;i<4;++i)read(A[i]);sort(A,A+4);
		if(A[0]+A[3]!=A[1]+A[2])puts("0");
		else{
			int cn=0;
			for(int i=0;i<=3;i+=3){
				for(int j=1;j<=2;j+=1){
					s[cn++]=pair<long long,long long>(A[i],A[j]);
					s[cn++]=pair<long long,long long>(A[j],A[i]);
				}
			}
			sort(s,s+cn);cn=unique(s,s+cn)-s;write(cn),pc('\n');
		}
	} 
	return 0;
}

B 「MCOI-03」村国

题目分析

一开始看到这题真的没有头绪,但是仔细思考后发现题面就是唬人的,感觉这样的题目还是挺有意思的。

假如当前好感值最高的点是 \(x\) ,那么会先选择一直去 \(x\) 直到 \(x\) 旁边出现了一个点的好感值和 \(x\) 相等并且编号尽可能小,不妨设这个点为 \(y\) ,那么就会一直先去 \(x,y\) 中编号小的,然后去 \(x,y\) 中编号大的一直循环,所以此时只需要判断 \(m\) 的奇偶性就行了。

需要注意的一点就是如果 \(x\) 不存在相邻的点答案就是 \(x\) 。

参考代码

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ch() getchar()
#define pc(x) putchar(x)
template<typename T>inline void read(T&x){
	int f;char c;
	for(f=1,c=ch();c<'0'||c>'9';c=ch())if(c=='-')f=-f;
	for(x=0;c<='9'&&c>='0';c=ch())x=x*10+(c&15);x*=f;
}
template<typename T>inline void write(T x){
	static char q[64];int cnt=0;
	if(!x)pc('0');if(x<0)pc('-'),x=-x;
	while(x)q[cnt++]=x%10+'0',x/=10;
	while(cnt--)pc(q[cnt]);
}
const int maxn=2000006;
int a[maxn];
int main(){
	int T;read(T);
	while(T--){
		int n;long long m;int po=0;read(n),read(m);
		for(int i=1;i<=n;++i){
			read(a[i]);if(a[i]>a[po])po=i;
		}
		int bo=0;
		for(int i=1;i<n;++i){
			int u,v;read(u),read(v);if(v==po)u^=v^=u^=v;
			if(u==po&&(a[v]>a[bo]||(a[v]==a[bo]&&v<bo)))bo=v;
		}
		if(!bo)write(po);
		else{
			int delta=a[po]-a[bo];
			if(m<delta)write(po);
			else{
				m-=delta;
				if(po>bo)po^=bo^=po^=bo;
				if(m&1)write(bo);else write(po);
			}
		}
		pc('\n');
	}
	return 0;
}

C 「MCOI-03」括号

题目分析

当 \(k=0\) 的时候,可以通过一个栈来求答案,不断删去匹配括号最后留下的串肯定是 )))...))((...((( ,答案就是这个串的长度,下面只考虑 \(k>0\) 的情况。

考虑 \(S(l,r)\) 的 0 级偏值给答案造成贡献时需要乘以的系数,要从串 \(S(1,n)\) 得到 \(S(l,r)\) 左端点需要向右边移动 \(l-1\) 次,右端点需要向左边移动 \(n-r\) 次,这些移动都是在 \(k\) 步里面完成的,由隔板法就可以得出要乘上的系数就是 \({l-1+k-1\choose k-1}\times {n-r+k-1\choose k-1}\) ,不妨设 \(S(l,r)\) 的 0 级偏值等于 \(T(l,r)\) ,那么答案就是 \(\sum_{l=1}^n\sum_{r=l}^n(T(l,r)\times {l-1+k-1\choose k-1}\times {n-r+k-1\choose k-1})\) 。

如何统计所有的 \(S(l,r)\) ?考虑从右边往左边扫,由 \(\sum_{r=l+1}^n(T(l+1,r)\times {n-r+k-1\choose k-1})\) 递推得出 \(\sum_{r=l}^n(T(l,r)\times {n-r+k-1\choose k-1})\) 。

首先需要知道,如果固定左端点,随着右端点的增加,不断删去匹配括号得到的串 )))...))((...((( 中的左半部分(即 )))...)) )的长度一定会不断增加,那么我们删去匹配括号最终保留的串肯定是这样的:

)))(...((
)))(...((
)))(...((
))(...((
))(...((
))(...((
)(...((
(...((
(...((
.
.
.
(

假如左边添加了一个 )

))))(...((
))))(...((
))))(...((
)))(...((
)))(...((
)))(...((
))(...((
)(...((
)(...((
.
.
.
)(
)

只是每个串的长度增加了 \(1\) ,所以此时满足:

\[\sum_{r=l}^n(T(l,r)\times {n-r+k-1\choose k-1})=\sum_{r=l}^n{n-r+k-1\choose k-1}+\sum_{r=l+1}^n(T(l+1,r)\times {n-r+k-1\choose k-1}) \]

假如左边添加了一个 (

()))(...((
()))(...((
()))(...((
())(...((
())(...((
())(...((
()(...((
((...((
((...((
.
.
.
((
(

此时可能出现匹配括号,需要把匹配括号删去:

  )(...((
  )(...((
  )(...((
  (...((
  (...((
  (...((
  (...((
((...((
((...((
.
.
.
((
(

不难发现,所有原本存在 ) 的子串的长度都减小了 \(2\) ,不妨设最小的满足 \(S(l+1,r)\) 左边保留了一个 ) 的 \(r\) 是 \(p\) ,那么可以得到:

\[\sum_{r=l}^n(T(l,r)\times {n-r+k-1\choose k-1})=\sum_{r=l}^n{n-r+k-1\choose k-1}-2\sum_{r=p}^n{n-r+k-1\choose k-1}+\sum_{r=l+1}^n(T(l+1,r)\times {n-r+k-1\choose k-1}) \]

由此我们可以得出,我们需要维护的就是 ) 数量不同的所有断点,不难发现这个是很好维护的,用一个栈维护就行了,时间复杂度 \(\mathcal O(n+k)\) 。

参考代码

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ch() getchar()
#define pc(x) putchar(x)
template<typename T>inline void read(T&x){
	int f;char c;
	for(f=1,c=ch();c<'0'||c>'9';c=ch())if(c=='-')f=-f;
	for(x=0;c<='9'&&c>='0';c=ch())x=x*10+(c&15);x*=f;
}
template<typename T>inline void write(T x){
	static char q[64];int cnt=0;
	if(!x)pc('0');if(x<0)pc('-'),x=-x;
	while(x)q[cnt++]=x%10+'0',x/=10;
	while(cnt--)pc(q[cnt]);
}
const int mod=998244353,maxn=2000005;
int mo(const int x){
	return x>=mod?x-mod:x;
}
int fac[maxn],iac[maxn];
int binom(int n,int m){
	return 1ll*iac[m]*iac[n-m]%mod*fac[n]%mod;
}
char s[maxn];
int st[maxn],tp;
int main(){
	int n,k;read(n),read(k);
	if(k==0){
		scanf("%s",s+1);
		int now=0,ans=0;
		for(int i=1;i<=n;++i){
			if(s[i]==')'){
				if(now)--now;
				else ++ans;
			}
			else ++now;
		}
		ans+=now;
		write(ans),pc('\n');
	}
	else{
		int mx=n+k;
		iac[0]=iac[1]=fac[0]=fac[1]=1;
		for(int i=2;i<=mx;++i)
			iac[i]=1ll*(mod-mod/i)*iac[mod%i]%mod;
		for(int i=2;i<=mx;++i)
			fac[i]=1ll*fac[i-1]*i%mod,iac[i]=1ll*iac[i-1]*iac[i]%mod;
		scanf("%s",s+1);
		int ans=0,sum=0,all=0;
		for(int i=n;i>=1;--i){
			sum=mo(sum+binom(n-i+k-1,k-1));
			all=mo(all+sum);
			if(s[i]=='('){
				if(tp){
					all=mo(mo(mo(mod-st[tp])<<1)+all);--tp;
				}
			}
			else{
				++tp;st[tp]=sum;
			}
			ans=mo(ans+1ll*all*binom(i-1+k-1,k-1)%mod);
		}
		write(ans),pc('\n');
	}
	return 0;
}

总结

这次月赛没有打多久,这个成绩勉强满意吧。

标签:11,...,ch,int,sum,choose,某古,游记,include
来源: https://www.cnblogs.com/lsq147/p/13907214.html

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

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

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

ICode9版权所有