ICode9

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

COMPFEST 14 - Preliminary Online Mirror(持续更新)

2022-09-12 17:33:59  阅读:201  来源: 互联网

标签:cnt const 14 int bmod Preliminary Mirror include define


Preface

9/10:今天不知道为什么一整天头疼的一批,而且牙也疼的吃不了饭,实在写不动题目啊

9/11:晚上发烧了,结果睡了一晚竟然好了……我的自愈能力原来这么强的嘛awa

9/12:得知错过了校队的第一轮选拔(没收到通知qaq),得等大一下才有机会了

不过自己写写题也比较轻松没什么压力,但接下来得准点打比赛了不能天天VP

下面题目做的顺序排,大致是按难度递增的把


A. Accumulation of Dominoes

SB题,注意特判\(m=1\)的情形

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
int n,m;
int main()
{
	scanf("%d%d",&n,&m); if (m==1) return printf("%d",n-1),0;
	return printf("%lld",1LL*n*(m-1)),0;
}

B. Basketball Together

SB题,贪心地从大到小考虑每个人为队长,拉队员的话就从小的开始拉

#include<cstdio>
#include<iostream>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005;
int n,d,a[N],ans;
int main()
{
	RI i,j; for (scanf("%d%d",&n,&d),i=1;i<=n;++i) scanf("%d",&a[i]);
	for (++d,sort(a+1,a+n+1),i=0,j=n;i<j;--j)
	{
		int k=(d-1)/a[j]; if (i+k<j) i+=k,++ans; else break;
	}
	return printf("%d",ans),0;
}

G. Garage

貌似之前有过哪个题目有这个结论的说

直接说结论,\(x\)是合法的当且仅当\(x\)是大于等于\(3\)的奇数大于等于\(8\)的\(4\)的倍数

证明,若\(x=2k+1,k\ge 1\),显然当\(b=k+1,a=k\)时符合,若\(x=4k+4,k\ge 1\),显然当\(b=k+2,a=k\)时符合

那么剩下来不符合的就是形如\(4k+2,k\ge 1\)的数了,不难发现由于\(a^2.b^2\)对\(4\)取模后的结果要么是\(0\)要么是\(1\),因此\(b^2-a^2\)对\(4\)取模的结果必不可能是\(2\)

计算答案的话可以直接二分,求\(\le x\)中有多少个合法的数即可

#include<cstdio>
#include<iostream>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
int n,ans;
inline int count(CI x)
{
	return (x+1)/2-1+(x>=4?x/4-1:0);
}
signed main()
{
	scanf("%lld",&n); int l=3,r=2147483647,mid;
	while (l<=r)
	{
		mid=l+r>>1; if (count(mid)>=n) ans=mid,r=mid-1; else l=mid+1;
	}
	return printf("%lld",ans),0;
}

M. Moving Both Hands

一个朴素的想法,设\(d(x,y)\)表示\(x\)到\(y\)的最短路,考虑枚举中间点,对于\((1,v)\)的答案就是\(\min_\limits{1\le i\le n} d(1,i)+d(v,i)\)

将原图中的边反向,设\(d'(x,y)\)表示反向图中\(x\)到\(y\)的最短路,此时答案为\(\min_\limits{1\le i\le n} d(1,i)+d'(i,v)\)

考虑对每个点增加一个状态,设\((x,0/1)\)表示到\(x\)的最短路,第二维表示是否反向,此时有:

  • 对于每条边\((u,v,w)\),连\((u,0)\to (v,0)\)权值为\(w\)的边,以及\((v,1)\to (u,1)\)权值为\(w\)的边
  • 对于每个点\(v\),连\((v,0)\to (v,1)\),权值为\(0\)的边

这样直接跑一遍Dijkstra即可,最后点\(v\)的答案就是\((1,0)\)到\((v,1)\)的最短路

#include<cstdio>
#include<queue>
#define RI register int
#define CI const int&
using namespace std;
const int N=200005;
const long long INF=1e18;
struct edge
{
	int to,nxt,v;
}e[N<<2]; int n,m,head[N],cnt,x,y,z; long long dis[N]; bool vis[N];
struct data
{
	long long v; int p;
	inline data(const long long& V=0,CI P=0) { v=V; p=P; }
	friend inline bool operator < (const data& A,const data& B)
	{
		return A.v>B.v;
	}
}; priority_queue <data> hp;
inline void addedge(CI x,CI y,CI z)
{
	e[++cnt]=(edge){y,head[x],z}; head[x]=cnt;
}
#define to e[i].to
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i; for (scanf("%d%d",&n,&m),i=1;i<=m;++i)
	scanf("%d%d%d",&x,&y,&z),addedge(x,y,z),addedge(n+y,n+x,z);
	for (i=1;i<=n;++i) addedge(i,n+i,0);
	for (i=1;i<=(n<<1);++i) dis[i]=INF; dis[1]=0;
	hp.push(data(dis[1],1)); while (!hp.empty())
	{
		int now=hp.top().p; hp.pop(); if (vis[now]) continue; vis[now]=1;
		for (i=head[now];i;i=e[i].nxt) if (dis[to]>dis[now]+e[i].v)
		hp.push(data(dis[to]=dis[now]+e[i].v,to));
	}
	for (i=2;i<=n;++i) printf("%lld ",dis[n+i]!=INF?dis[n+i]:-1);
	return 0;
}

C. Circular Mirror

首先不难发现存在直角三角形的充要条件是:存在某个颜色,其颜色点数大于等于\(3\)且其中的两点恰好在一直径上

首先我们可以扫一遍求出一共有多少对点对在一直径上,记为\(cnt\),剩下的自由点记为\(left=n-cnt*2\)

考虑枚举恰好有多少对直径点对的颜色相同,记为\(i\),那么此时的贡献即为:

\[C_{cnt}^i\times C_m^i\times i!\times [(m-i)\times (m-i-1)]^{cnt-i}\times (m-i)^{left} \]

首先前面的\(C_{cnt}^i\times C_m^i\times i!\)表示从\(cnt\)个点对中选出\(i\)对并且找出\(i\)种颜色一一匹配的方案数,\([(m-i)\times (m-i-1)]^{cnt-i}\)表示剩余的\(cnt-i\)个点对的选法(此时两两颜色不同),\((m-i)^{left}\)表示剩下的自由点的选法

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=300005,mod=998244353;
int n,m,a[N],cnt,fac[N],ifac[N],ans; long long pfx[N],sum;
inline int quick_pow(int x,int p=mod-2,int mul=1)
{
	for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
inline void init(CI n)
{
	RI i; for (fac[0]=i=1;i<=n;++i) fac[i]=1LL*fac[i-1]*i%mod;
	for (ifac[n]=quick_pow(fac[n]),i=n-1;~i;--i) ifac[i]=1LL*ifac[i+1]*(i+1)%mod;
}
inline int C(CI n,CI m)
{
	return 1LL*fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i,j; for (scanf("%d%d",&n,&m),i=1;i<=n;++i)
	scanf("%d",&a[i]),pfx[i]=pfx[i-1]+a[i]; sum=pfx[n];
	if (sum%2==0)
	{
		for (j=0,i=1;i<n;++i)
		{
			while (pfx[i]-pfx[j]>sum/2LL) ++j;
			if (pfx[i]-pfx[j]==sum/2LL) ++cnt;
		}
	}
	for (init(max(m,cnt)),i=0;i<=min(m,cnt);++i)
	(ans+=1LL*C(cnt,i)*C(m,i)%mod*fac[i]%mod*quick_pow(1LL*(m-i)*(m-i-1)%mod,cnt-i)%mod*quick_pow(m-i,n-cnt*2)%mod)%=mod;
	return printf("%d",ans),0;
}

H. Hot Black Hot White

昨天不小心漏看了这道过的人300+的题了,其实比H,C都简单啊(触发:构造题精通

首先由于模\(3\)的性质可以转为求一个数每位上数字的和,因此\(\operatorname{concat}(x,y)\equiv(x+y)\mod 3\)

因此\(\operatorname{concat}(A_i, A_j) \times \operatorname{concat}(A_j, A_i) + A_i \times A_j \equiv (A_i+A_j)^2+A_i\times A_j \equiv A_i^2+A_j^2\mod 3\)

稍加讨论,我们发现\(A_i^2\bmod 3\)的值只可能是\(0/1\),一个naive的想法,令\(Z=0/2\),把所有\(A_i^2\bmod 3=0\)的数变白,把所有\(A_i^2\bmod 3=1\)的数变黑,即满足和不会反应的条件

那么这样不一定满足颜色的个数相等,因此我们讨论一下:

  • 若\(A_i^2\bmod 3=0\)的数的个数更多,则令\(Z=2\),此时可以给\(A_i^2\bmod 3=0\)的一些数赋予另一种颜色而保持不会发生反应的特性
  • 若\(A_i^2\bmod 3=1\)的数的个数更多,则令\(Z=0\),此时可以给\(A_i^2\bmod 3=1\)的一些数赋予另一种颜色而保持不会发生反应的特性
#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005;
int n,a[N],b[N],c[2],cnt;
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i; for (scanf("%d",&n),i=1;i<=n;++i)
	scanf("%d",&a[i]),++c[b[i]=1LL*a[i]*a[i]%3];
	if (c[0]>=c[1])
	{
		for (puts("2"),i=1;i<=n;++i) if (b[i]==1) putchar('1');
		else if (b[i]==0&&cnt<n/2) putchar('0'),++cnt; else putchar('1');
	} else
	{
		for (puts("0"),i=1;i<=n;++i) if (b[i]==0) putchar('0');
		else if (b[i]==1&&cnt<n/2) putchar('1'),++cnt; else putchar('0');
	}
	return 0;
}

F. Field Photography

首先由于移动的次数不限,并且最后要满足或起来是一个数,我们考虑令\(k=\operatorname{LSB}(W_j)\),其中\(\operatorname{LSB}(x)\)表示\(x\)的二进制下从低位到高位第一个\(1\)的位置

不难发现由于或的性质,我们每次操作的步数必须是\(2^k\)的倍数,考虑以下一种移动方案:

  • 每次对某一行向左或向右移动\(2^k\)的步数
  • 最后将某一行先向右移动\(W_j\)的步数,然后再向左移动\(W_j\)的步数

不难发现这样一定是最优的(每次移动的单位长度最短)并且满足题目要求

不难发现此时我们只关心区间端点对\(2^k\)取模后的结果,具体的:

  • 若\(r_i-l_i+1\ge 2^k\) ,则\([0,2^k)\)中的每个数都能被覆盖到
  • 若\(r_i-l_i+1< 2^k\and l_i\bmod 2^k\le r_i\bmod 2^k\),则\([l_i\bmod 2^k,r_i\bmod 2^k]\)中的每个数都能被覆盖到
  • 若\(r_i-l_i+1< 2^k\and l_i\bmod 2^k> r_i\bmod 2^k\),则\([l_i\bmod 2^k,2^k),[0,r_i\bmod 2^k]\)中的每个数都能被覆盖到

因此问题变为区间修改+全局最值,结果我这个傻狗去写线段树,然后常数太大T了,后来一想发现直接差分就好了

由于\(\operatorname{LSB}(x)\)的范围是\(\log W_j\)级别的,总复杂度\(O(n\log n\log W_j)\)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<utility>
#define RI register int
#define CI const int&
#define mp make_pair
#define fi first
#define se second
using namespace std;
const int N=100005;
typedef pair <int,int> pi;
int n,l[N],r[N],q,x,ans[35],cnt,sum; pi rst[N<<2];
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i,j; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d%d",&l[i],&r[i]);
	for (j=0;j<=30;++j)
	{
		int k=1<<j; for (cnt=0,i=1;i<=n;++i)
		if (r[i]-l[i]+1>=k) rst[++cnt]=mp(0,1),rst[++cnt]=mp(k,-1);
		else if (l[i]%k<=r[i]%k) rst[++cnt]=mp(l[i]%k,1),rst[++cnt]=mp(r[i]%k+1,-1);
		else rst[++cnt]=mp(l[i]%k,1),rst[++cnt]=mp(k,-1),rst[++cnt]=mp(0,1),rst[++cnt]=mp(r[i]%k+1,-1);
		for (sort(rst+1,rst+cnt+1),sum=0,i=1;i<=cnt;++i)
		sum+=rst[i].se,ans[j]=max(ans[j],sum);
	}
	for (scanf("%d",&q),i=1;i<=q;++i)
	for (scanf("%d",&x),j=0;j<=30;++j)
	if ((x>>j)&1) { printf("%d\n",ans[j]); break; }
	return 0;
}

标签:cnt,const,14,int,bmod,Preliminary,Mirror,include,define
来源: https://www.cnblogs.com/cjjsb/p/16686695.html

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

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

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

ICode9版权所有