首页 > 其他分享 >AtCoder Regular Contest 149(持续更新)

AtCoder Regular Contest 149(持续更新)

时间:2022-10-04 23:33:07浏览次数:84  
标签:AtCoder CI const Contest int 149 include RI define

Preface

最近国庆在外面玩的有点high啊,欠了一篇AT和两篇CF没写,今天先浅浅写一下这场

当时10.2号在外面玩得有点晚了,到寝室刚好比赛开始,晚饭都没吃就开干了

主要是C写的太久了,而且挂了一发之后看了好久才发现\(n=3\)的情形没处理好

然后40min做D没做出来,鉴定为纯纯的FW(话说原来ARC这么难的吗,感觉比以前的一些AGC还难)


A - Repdigit Number

送分题,暴力枚举每一种情况判断即可

#include<cstdio>
#define RI register int
#define CI const int&
using namespace std;
int n,m,md,mn=-1;
inline void print(CI d,CI n)
{
	for (RI i=1;i<=n;++i) putchar(d+'0');
}
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i,j; for (scanf("%d%d",&n,&m),j=1;j<=9;++j)
	{
		int cur=0; for (i=1;i<=n;++i)
		if ((cur=(10LL*cur+j)%m)==0)
		{
			if (i>mn||(i==mn&&j>md)) mn=i,md=j;
		}
	}
	if (~mn) print(md,mn); else puts("-1");
	return 0;
}

B - Two LIS Sum

一眼猜结论题,不难发现我们将\(A\)排成\(1,2,\cdots,n\)时答案一定不会变劣,因此在此基础上求出\(B\)的LIS即可

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=300005;
int n,a[N],x,b[N],cur,ans;
class Tree_Array
{
	private:
		int bit[N];
	public:
		#define lowbit(x) (x&-x)
		inline void add(int x,CI y)
		{
			for (;x<=n;x+=lowbit(x)) bit[x]=max(bit[x],y);
		}
		inline int get(int x,int ret=0)
		{
			for (;x;x-=lowbit(x)) ret=max(ret,bit[x]); return ret;
		}
		#undef lowbit
}T;
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]);
	for (i=1;i<=n;++i) scanf("%d",&x),b[a[i]]=x;
	for (i=1;i<=n;++i) cur=T.get(b[i]),T.add(b[i],cur+1),ans=max(ans,cur+1);
	return printf("%d",ans+n),0;
}

C - Avoid Prime Sum

又是比较显然的构造题,不难发现奇数+奇数、偶数+偶数的和一定为合数,因此我们考虑尽可能地让奇数之间,偶数之间尽量邻近在一起

因此就有一个naive的想法,根据\(n\)的奇偶性把棋盘分成两个部分(如下图),每个部分各自填奇数和偶数,然后只要考虑交界处的情况了

偶数的情况比较容易,只要找到一个奇数且不是质数的数然后拆分一下即可,但奇数时要讨论最中间的奇数要和两个偶数之和为合数

可能我的实现比较渣,代码量挺大,而且还需要特判\(n=3\)的情况(话说我\(n=3\)的情况手玩玩不出来最后还是暴枚出来的)

后来看了眼官方sol发现可以直接用\(3\)的倍数来构造,这样大大降低了代码复杂度

#include<cstdio>
#include<iostream>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=1005;
const int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
int n,a[N][N],tar,odd[N],even[N],spo=-1,spe,arr[N]; bool vis[N*N];
inline bool is_prime(CI n)
{
	for (RI i=2;i*i<=n;++i)
	if (n%i==0) return 0; return 1;
}
inline bool check(CI t)
{
	for (RI i=1;i<=n;++i)
	{
		odd[i]=i; even[i]=t-i; if ((t-i)&1) swap(odd[i],even[i]);
		if (i!=1&&!is_prime(even[i]+1)) spo=odd[i],spe=even[i];
	}
	return ~spo;
}
inline void sp_solve(void)
{
	RI i,j,k; for (i=1;i<=9;++i) arr[i]=i;
	do
	{
		for (k=0,i=1;i<=3;++i) for (j=1;j<=3;++j) a[i][j]=arr[++k];
		bool flag=1; for (i=1;i<=3&&flag;++i) for (j=1;j<=3&&flag;++j) for (k=0;k<4&&flag;++k)
		{
			int ii=i+dx[k],jj=j+dy[k]; if (ii<1||ii>3||jj<1||jj>3) continue;
			if (is_prime(a[i][j]+a[ii][jj])) flag=0;
		}
		if (flag) return;
	} while (next_permutation(arr+1,arr+10));
}
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i,j,k; if (scanf("%d",&n),n==3) sp_solve(); else
	{
		if (n&1)
		{
			for (i=2*n+1;i<=n*n;i+=2)
			if (!is_prime(i)&&check(i)) break;
			a[(n+1)/2][(n+1)/2]=1; a[(n+1)/2+1][(n+1)/2]=even[1];
			a[(n+1)/2][(n+1)/2+1]=spe; a[(n+1)/2-1][(n+1)/2+1]=spo;
			vis[1]=vis[even[1]]=vis[spe]=vis[spo]=1;
			for (i=j=1;i<(n+1)/2;++i)
			{
				if (odd[++j]==spo) ++j; vis[a[(n+1)/2][i]=odd[j]]=1;
			}
			for (i=(n+1)/2+2;i<=n;++i)
			{
				if (odd[++j]==spo) ++j; vis[a[(n+1)/2-1][i]=odd[j]]=1;
			}
			for (i=j=1;i<(n+1)/2;++i)
			{
				if (even[++j]==spe) ++j; vis[a[(n+1)/2+1][i]=even[j]]=1;
			}
			for (i=(n+1)/2+2;i<=n;++i)
			{
				if (even[++j]==spe) ++j; vis[a[(n+1)/2][i]=even[j]]=1;
			}
			for (k=1,i=1;i<(n+1)/2-1;++i) for (j=1;j<=n;++j)
			{
				while (vis[k]) k+=2; vis[a[i][j]=k]=1;
			}
			for (i=1;i<=(n+1)/2;++i)
			{
				while (vis[k]) k+=2; vis[a[(n+1)/2-1][i]=k]=1;
			}
			for (k=2,i=(n+1)/2+2;i<=n;++i) for (j=1;j<=n;++j)
			{
				while (vis[k]) k+=2; vis[a[i][j]=k]=1;
			}
			for (i=(n+1)/2+1;i<=n;++i)
			{
				while (vis[k]) k+=2; vis[a[(n+1)/2+1][i]=k]=1;
			}
		} else
		{
			for (i=2*n+1;i<=n*n;i+=2)
			if (!is_prime(i)) { check(i); break; }
			for (i=1;i<=n;++i) vis[a[n/2][i]=odd[i]]=1,vis[a[n/2+1][i]=even[i]]=1;
			for (k=1,i=1;i<n/2;++i) for (j=1;j<=n;++j)
			{
				while (vis[k]) k+=2; vis[a[i][j]=k]=1;
			}
			for (k=2,i=n/2+2;i<=n;++i) for (j=1;j<=n;++j)
			{
				while (vis[k]) k+=2; vis[a[i][j]=k]=1;
			}
		}
	}
	for (i=1;i<=n;++i) for (j=1;j<=n;++j) printf("%d%c",a[i][j]," \n"[j==n]);
	return 0;
}

D - Simultaneous Sugoroku

当时比赛的时候想的方向有点偏了,结果G了

首先我们直接考虑所有的\([1,10^6]\)的pieces,然后可以发现一个重要的性质:

对于\(t,-t\)两个位置的pieces,它们如果到达原点那时间必然时相同的,若无法到达最后的位置关于原点对称

初始时所有的pieces都在一个半轴上,不难发现在每次移动后就可能会出现正负半轴上都有pieces的情况

但我们利用上面的性质,总是可以把其中那个pieces数量较少的半轴上的pieces全部合并到另一个半轴上去,具体地我们可以连一条边在这两个点之间(可以看下图帮助理解)

然后每次有piece到达原点的时候统计答案即可,最后所有点之间构成了一个森林,更新答案即可

#include<cstdio>
#include<vector>
#define RI register int
#define CI const int&
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
const int N=1000005;
int n,m,x[N],d[N]; pair <int,int> ans[N]; vector <int> v[N]; bool vis[N];
inline void DFS(CI now)
{
	vis[now]=1; for (int to:v[now]) if (!vis[to])
	{
		if (ans[now].fi==1) ans[to]=ans[now]; else ans[to]=mp(0,-ans[now].se); DFS(to);
	}
}
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",&x[i]);
	for (i=1;i<=m;++i) scanf("%d",&d[i]);
	for (i=1;i<=1000000;++i) ans[i].first=-1; int l=1,r=1000000,mid,sum=0;
	for (i=1;i<=m;++i)
	{
		if (l>r) break; if (l+sum>0) sum-=d[i]; else sum+=d[i]; mid=-sum;
		if (mid<l||mid>r) continue; ans[mid]=mp(1,i);
		if (mid-l<=r-mid)
		{
			for (j=l;j<mid;++j) v[2*mid-j].pb(j); l=mid+1;
		} else
		{
			for (j=mid+1;j<=r;++j) v[2*mid-j].pb(j); r=mid-1;
		}
	}
	for (i=l;i<=r;++i) ans[i]=mp(0,i+sum);
	for (i=1;i<=1000000;++i) if (!vis[i]&&~ans[i].fi) DFS(i);
	for (i=1;i<=n;++i) printf("%s %d\n",ans[x[i]].fi?"Yes":"No",ans[x[i]].se);
	return 0;
}

标签:AtCoder,CI,const,Contest,int,149,include,RI,define
From: https://www.cnblogs.com/cjjsb/p/16754829.html

相关文章

  • AtCoder Regular Contest 149
    A发现所有数字都相同的数一共只有\(10^6\)种,考虑枚举每种情况,关键在于如何判断一个数\(\bmodm\)是否为\(0\)。考虑\(9\bmod8=1\),而\(99\bmod8=(9\times10+9)\b......
  • AtCoder Beginner Contest 271
    AtCoderBeginnerContest271D-FlipandAdjust一共有\(N\)张牌,每一面都写着一个整数。卡\(i(1\lei\leN)\)前面写着整数\(a_i\),后面写着整数\(b_i\)。你可......
  • AtCoder Regular Contest 137 D
    一道很好的题目,运用了很多不同的技巧。结论1:枚举变换次数\(k\),若\(A_{i}\)对答案有贡献,当且仅当\(C_{n-i+k-1}^{k-1}\equiv1\mod2\)。首先我们可以统计\(A_{p}\)对......
  • Atcoder 题目选做
    ABC257G直接考虑\(\rmKMP\)的过程。\(\rmKMP\)可以帮助我们求出\(S\)的\(border\),并找到\(T\)中每一个位置能匹配上的\(S\)的最长前缀。那么我们就可以很......
  • CSP模拟练习赛1 https://www.luogu.com.cn/contest/82861#problems
    P1321单词覆盖还原简单思路字符串#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<map>#definelllonglon......
  • ARC149E Sliding Window Sort(组合)
    ARC149ESlidingWindowSort给定\(M,K\)和\(N\)排列\(B\)。问对\(i=0\toK-1\)依次执行对\(j=0\toM-1,A_{(i+j)\bmodN}\)这段循环区间排序,最......
  • 【合集】AtCoder 比赛题解
    PartAABCABC266(A-Ex)ABC267(A-G)ABC268(A-D)ABC269(A-F)ABC270(D-E)ABC271(C-F)PartBARCARC148(C)......
  • codeforces/AtCoder补题整理
    目录cf1738CEvenNumberAddicts(博弈/记忆化搜索)题意题解cf1739EResetKEdges(树,二分+贪心)题意题解cf1730DPrefixesandSuffixes(字符串,思维)题意题解cf1734DS......
  • ARC149D Simultaneous Sugoroku(并查集)
    ARC149DSimultaneousSugoroku有\(N\)个数\(X_i\)和\(M\)个数\(D_i\),对每个\(X_i\)询问依次对\(j=1\ton\)执行:如果\(X_i>0\)就\(-D_j\),如果\(X_i<......
  • solution-arc149(ABC)
    A就是枚举,先枚举是哪个数再枚举位数。把这种题放arcA感觉挺没意思。#include<cstdio>usingnamespacestd;intansx,ansy;voidcheckmax(inti,intj){if(......