codeforces good bye 2018

codeforces good bye 2018

good bye candidate master

2018年的最后一场cf

感觉打完我又用rating换了一大波rp

T1

题意: 给出三个数rby,定义abc是分别小于等于这三个数且满足a+2==b+1=c

a+b+c的最大值

题解: 日常读错题,zz的我考场上没看清楚题面以为是要求a>b>c,样例没测就交了。。。WA*1

实际上只要枚举一下abc那个取了最大值就好了,,,要满足答案最大,一定有一个是取最大值的

代码:

#include<map>
#include<queue>
#include<cmath>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int a,b,c;
int main(){
//	freopen("1.in","r",stdin);
	scanf("%d%d%d",&a,&b,&c);
	if(a+1<=b&&a+2<=c) printf("%d\n",3*a+3);
	else
	if(b<=a+1&&b+1<=c) printf("%d\n",3*b);
	else
	printf("%d\n",3*c-3);
	return 0;
}

T2

题意:给出n个标志物坐标(xi,yi)以及n个线索(ai,bi),要把标志物和线索两两匹配使得所有(xi+a[pi],yi+a[yi])相等

题解:本来是想要先枚举第一个坐标所匹配的线索,然后判断是否存在匹配方案使得宝藏坐标等于枚举出的坐标,这样时间复杂度n2logn应该也能过,虽然有点zz

然而其实这道题可以nlogn过:要想每个都相等,对于最小的x坐标,一定要给他最大的a来补,对于y也是一样。。

这样的话sort一遍就好了

代码:

#include<map>
#include<queue>
#include<cmath>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1100;
struct node{
	int x,y;
}e[maxn],t[maxn];
int n;
bool cmp(node x,node y){return x.x<y.x;}
bool Cmp(node x,node y){return x.y<y.y;}
int main(){
//	freopen("1.in","r",stdin);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d%d",&e[i].x,&e[i].y);
	for(int i=1;i<=n;i++)
		scanf("%d%d",&t[i].x,&t[i].y);
	sort(e+1,e+n+1,cmp);
	sort(t+1,t+n+1,cmp);
	printf("%d ",e[1].x+t[n].x);
	sort(e+1,e+n+1,Cmp);
	sort(t+1,t+n+1,Cmp);
	printf("%d\n",e[1].y+t[n].y);
	return 0;
}

T3

题意:n个元素的环,编号为1~n,一个球一开始在1,每次可以顺时针移动k步,每移动到一个点上就会产生这个点的编号点贡献,再次到1时停止,问对于所有k,能产生哪几种不同的总贡献

题解:对于n的每一个约数都统计一下就好了,不要忘记去重

代码:

#include<map>
#include<queue>
#include<cmath>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e7+100;
int n,tot;
ll p[maxn];
inline int work(int n,int x){
	ll tmp=n/x;
	p[++tot]=n*(tmp-1)/2+tmp;
}
int main(){
//	freopen("1.in","r",stdin);
	scanf("%d",&n);
	for(int i=1;i*i<=n;i++)
		if(n%i==0){
			work(n,i),work(n,n/i); 
		}
	sort(p+1,p+tot+1);p[0]=-1;
	for(int i=1;i<=tot;i++)
		if(p[i]!=p[i-1]) printf("%I64d ",p[i]);
	printf("\n");
	return 0;
}

T4

题意:把n个元素的所有排列按字典序头尾相接,形成一个长为nn!的数列a,问有多少对l,r满足

a[l]+a[l+1]+...+a[r1]+a[r]=n(n+1)/2

题解:分析了一下样例,很显然的可以发现只有当l,r代表的是一个排列的时候才会等于n(n+1)/2,就考虑对于每个排列,他对答案的贡献

想象对于每个答案排列,他都可以分为两部分,一部分属于a中的前一个排列末尾,一个属于后一个排列开头,因为排列总数是n!,对于一个排列分法有n种,所以总方案应是nn!

但是这些方案中有一些是不合法的,比如:(n=5,设x是前一个末尾,y是后一个开头)

x={4,2},y={1,3,5}

显然,完整的前一个应该是{1,3,5,4,2},但是我们发现,后一个是不会合法的,因为他要满足比前一个大,但是前一个的最后两位(即x)是单减的,也就是说没有比x大的了。

那么我们枚举所有长度的单减序列,长度为i的单减序列总数就等于在一个{n,n1,n2,...,1}的序列里挑i个数,即C(n,i),对于每个单减序列x,他的y是可以随便填的(这里的x,y还是上面的定义),方案总数(ni)!

然后就没有然后了,总方案数nn!,不合法方案数i=1nC(n,i)(ni)!,合法方案就是:

ans=nn!i=1nC(n,i)(ni)!

如果你没有和zz的nianheng一样在手算时zz地把4!算成16,你就能马上A掉这道题了

代码:

#include<map>
#include<queue>
#include<cmath>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e7+100,P=998244353;
int n;
ll jc[maxn],ans;
void ycl(){
	jc[0]=1;
	for(int i=1;i<=n;i++)
		jc[i]=jc[i-1]*i%P;
}
inline ll poww(ll x,ll y){
	ll base=1;
	while(y){
		if(y&1) base=base*x%P;
		x=x*x%P;
		y>>=1;
	}
	return base;
}
inline ll C(int n,int m){
	return jc[n]*poww(jc[m],P-2)%P*poww(jc[n-m],P-2)%P;
}
int main(){
//	freopen("1.in","r",stdin);
	scanf("%d",&n);
	ycl();
	for(int i=1;i<=n;i++)
		ans=(ans+C(n,i)*jc[n-i]%P)%P;
	ans=(jc[n]*n%P-ans)%P;
	printf("%I64d\n",(ans+1)%P);
	return 0;
}

感想

失误辣么多,我还是太蒻了啊

posted @   nianheng  阅读(263)  评论(0编辑  收藏  举报
编辑推荐:
· .NET 依赖注入中的 Captive Dependency
· .NET Core 对象分配(Alloc)底层原理浅谈
· 聊一聊 C#异步 任务延续的三种底层玩法
· 敏捷开发:如何高效开每日站会
· 为什么 .NET8线程池 容易引发线程饥饿
阅读排行:
· 终于决定:把自己家的能源管理系统开源了!
· 外部H5唤起常用小程序链接规则整理
· C#实现 Winform 程序在系统托盘显示图标 & 开机自启动
· 了解 ASP.NET Core 中的中间件
· 详解:订单履约系统规划
点击右上角即可分享
微信分享提示