Pbri

Codeforces Round #741 (Div. 2) 题解

Codeforces Round #741 (Div. 2) 题解

A

答案就是 \(r \mod{\max(l,r/2+1)}\)

\(code\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#define FUP(i,x,y) for(int i=(x);i<=(y);i++)
#define FDW(i,x,y) for(int i=(x);i>=(y);i--)
#define FED(i,x) for(int i=head[x];i;i=ed[i].nxt)
#define pr pair<int,int>
#define mkp(a,b) make_pair(a,b)
#define fi first
#define se second
#define MAXN 100010
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-9
#define MOD 1000000007
#define ll long long
#define db double
using namespace std;
int read()
{
	int w=0,flg=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-'){flg=-1;}ch=getchar();}
	while(ch<='9'&&ch>='0'){w=w*10+ch-'0',ch=getchar();}
	return w*flg;
}
int T;
int l,r;
void solve()
{
	l=read(),r=read();
	int re=max(l,r/2+1);
	printf("%d\n",r%re);
}
int main(){
	T=read();
	while(T--) solve();
	return 0;
}

B

各种特判即可,代码很详细。好像没有判 \(3\) 的情况,不过因为别的情况都涵盖了所以可能无所谓?

\(code\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#define FUP(i,x,y) for(int i=(x);i<=(y);i++)
#define FDW(i,x,y) for(int i=(x);i>=(y);i--)
#define FED(i,x) for(int i=head[x];i;i=ed[i].nxt)
#define pr pair<int,int>
#define mkp(a,b) make_pair(a,b)
#define fi first
#define se second
#define MAXN 100010
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-9
#define MOD 1000000007
#define ll long long
#define db double
using namespace std;
int read()
{
	int w=0,flg=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-'){flg=-1;}ch=getchar();}
	while(ch<='9'&&ch>='0'){w=w*10+ch-'0',ch=getchar();}
	return w*flg;
}
int T;
int n;
char s[MAXN];
int cnt[10],cx[10];
void solve()
{
	FUP(i,1,9) cnt[i]=cx[i]=0;
	n=read();
	scanf("%s",s+1);
	FUP(i,1,n)
	{
		if(s[i]!='2'&&s[i]!='3'&&s[i]!='5'&&s[i]!='7')
		{
			puts("1");
			putchar(s[i]);
			puts("");
			return;
		}
		cnt[s[i]-'0']++;
		cx[s[i]-'0']=i;
	}
	if(n==2)
	{
		puts("2");
		printf("%s\n",s+1);
		return;
	}
	if(cx[2]>1)
	{
		printf("2\n%c2\n",s[1]);
		return;
	}
	if(cx[5]>1)
	{
		printf("2\n%c5\n",s[1]);
		return;
	}
	if(cnt[3]>1)
	{
		puts("2\n33");
		return;
	}
	if(cnt[7]>1)
	{
		puts("2\n77");
		return;
	}
	if(cx[5])
	{
		if(cx[5]<cx[7]) puts("2\n57");
		else puts("2\n75");
	}
	else
	{
		if(cx[2]<cx[7]) puts("2\n27");
		else puts("2\n72");
	}
}
int main(){
	T=read();
	while(T--) solve();
	return 0;
}

C

如果有一位是 \(0\) ,设它在 \(p\) 。如果它在前半段就选 \([p+1,n],[p,n]\) 如果在后半段就选 \([1,p-1],[1,p]\) ,否则全是 \(1\) ,随便构造即可。

\(code\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#define FUP(i,x,y) for(int i=(x);i<=(y);i++)
#define FDW(i,x,y) for(int i=(x);i>=(y);i--)
#define FED(i,x) for(int i=head[x];i;i=ed[i].nxt)
#define pr pair<int,int>
#define mkp(a,b) make_pair(a,b)
#define fi first
#define se second
#define MAXN 100010
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-9
#define MOD 1000000007
#define ll long long
#define db double
using namespace std;
int read()
{
	int w=0,flg=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-'){flg=-1;}ch=getchar();}
	while(ch<='9'&&ch>='0'){w=w*10+ch-'0',ch=getchar();}
	return w*flg;
}
int T;
int n;
char s[MAXN];
void solve()
{
	n=read();
	scanf("%s",s+1);
	FUP(i,1,n)
	{
		if(s[i]=='0')
		{
			if(i>n/2) printf("%d %d %d %d\n",1,i,1,i-1);
			else printf("%d %d %d %d\n",i,n,i+1,n);
			return;
		}
	}
	printf("%d %d %d %d\n",1,n/2,n-n/2+1,n);
}
int main(){
	T=read();
	while(T--) solve();
	return 0;
}

D

如果一开始这个区间的和就是 \(0\) ,那么答案就是 \(0\) 。如果这个区间长度是奇数,那么答案就是 \(1\) 。令前缀和数组是 \(s\) ,构造方法是找到一个位置 \(p\) 满足 \(s_p+s_{p+1}=s_r\) ,因为它的前缀和变化是 \(1\) ,那么变到 \(s_r\) 过程中肯定存在这么一个位置,保证了解的存在性。如果区间长度是偶数,那么答案就是 \(2\) ,构造方法是,先去掉最后一个就变成奇数情况了。然后直接对每个前后之和放进 \(vector\) 里面二分即可。

\(code\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <vector>
#define FUP(i,x,y) for(int i=(x);i<=(y);i++)
#define FDW(i,x,y) for(int i=(x);i>=(y);i--)
#define FED(i,x) for(int i=head[x];i;i=ed[i].nxt)
#define pr pair<int,int>
#define mkp(a,b) make_pair(a,b)
#define fi first
#define se second
#define MAXN 1200010
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-9
#define MOD 1000000007
#define ll long long
#define db double
using namespace std;
int read()
{
	int w=0,flg=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-'){flg=-1;}ch=getchar();}
	while(ch<='9'&&ch>='0'){w=w*10+ch-'0',ch=getchar();}
	return w*flg;
}
int T;
int n,q,s[MAXN];
char str[MAXN];
vector<int>vc[MAXN];
void solve()
{
	FUP(i,0,4*n+1) vc[i].clear();
	n=read(),q=read();
	scanf("%s",str+1);
	FUP(i,1,n)
	{
		int a=i%2?1:-1;
		int b=str[i]=='+'?1:-1;
		s[i]=s[i-1]+a*b;
			//if(abs(s[i]+s[i-1])>n) continue;
			//printf("i=%d pos=%d\n",i,(s[i]+s[i-1]+2*n+1)%(2*n+1));
		vc[s[i]+s[i-1]+2*n].push_back(i-1);
		//printf("%d ",s[i]);
	}
	//puts("");
	FUP(i,1,q)
	{
		int l=read(),r=read();
		if(s[r]-s[l-1]==0) puts("0");
		else if((r-l+1)&1)
		{
			puts("1");
			if(l==r) printf("%d\n",l);
			else
			{
				int w=s[l-1]+s[r]+2*n;
				int re=lower_bound(vc[w].begin(),vc[w].end(),l-1)-vc[w].begin();
				printf("%d\n",vc[w][re]+1);
			}
		} 
		else
		{
			puts("2");
			printf("%d ",r);
			r--;
			if(l==r) printf("%d\n",l);
			else
			{
				int w=s[l-1]+s[r]+2*n;
				//printf("w=%d\n",w);
				int re=lower_bound(vc[w].begin(),vc[w].end(),l-1)-vc[w].begin();
				printf("%d\n",vc[w][re]+1);
			}
			
		}
		//puts("########");
	}
	//puts("##########################");
}
int main(){
	T=read();
	while(T--) solve();
	return 0;
}

E

考场傻逼有个地方没特判,后来贺了个后缀排序的板子,实际上挺简单。就是说你逆序去 \(dp\) ,用一个后缀去更新左端点在左边的后缀的答案。那么你考虑说如果你 \(s_p>s_{p'}\) ,那么你的答案就完全可以接在它后面,所以 \(dp_{p'}=\max(dp_{p'},dp_p+(n-p'+1))\) 后面那个是 \(p'\) 自己的答案。如果这一位相等,那么就考虑 \(p+1\)\(p'+1\) 的贡献就是 \(p\)\(p'\) 的贡献,特判这个贡献为零,那个时候 \(p\) 的后缀要小。当然每个位置的 \(n-i+1\) 的答案也要用来更新自己的答案(万一后面没人能更新自己呢呢)。

\(code\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#define FUP(i,x,y) for(int i=(x);i<=(y);i++)
#define FDW(i,x,y) for(int i=(x);i>=(y);i--)
#define FED(i,x) for(int i=head[x];i;i=ed[i].nxt)
#define pr pair<int,int>
#define mkp(a,b) make_pair(a,b)
#define fi first
#define se second
#define MAXN 5010
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-9
#define MOD 1000000007
#define ll long long
#define db double
using namespace std;
int read()
{
	int w=0,flg=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-'){flg=-1;}ch=getchar();}
	while(ch<='9'&&ch>='0'){w=w*10+ch-'0',ch=getchar();}
	return w*flg;
}
int T;
int n,del[MAXN][MAXN],dp[MAXN],ans;
char s[MAXN];
void solve()
{
	FUP(i,1,n)
	{
		dp[i]=0;
		FUP(j,1,i-1) del[i][j]=0;
	}
	n=read(),ans=0;
	scanf("%s",s+1);
	FDW(i,n,1)
	{
		dp[i]=max(dp[i],n-i+1);
		ans=max(ans,dp[i]);
		//printf("i=%d dp=%d\n",i,dp[i]);
		FDW(j,i-1,1)
		{
			if(s[i]>s[j])
			{
				del[i][j]=n-j+1;
				dp[j]=max(dp[j],dp[i]+del[i][j]);
			}
			else if(s[i]==s[j])
			{
				del[i][j]=del[i+1][j+1];
				if(del[i+1][j+1]) dp[j]=max(dp[j],dp[i]+del[i][j]);
			}
		}
	}
	printf("%d\n",ans);
}
int main(){
	T=read();
	while(T--) solve();
	return 0;
}

F

屑随机题。考虑构造一个 \(n^2\) 的做法。求出每一对儿的 \(\text{lcm}\) ,那么最大的那一对一定是 \(r-1\)\(r\) ,然后再根别人问问看看 \(\text{lcm}\) 里有没有 \(r\) 即可判断哪一个是 \(r\) ,然后重复这个算法即可。然后 \(n\le 100\) 就解决了。如果比较大考虑说我们如果找到了一个大于 \(\dfrac{r}{2}\) 的质数那么我们就能根据这个位置求出别的位置的答案。那么我们可以随机 \(5000\) 对数,找出这些 \(\text{lcm}\) 中最大的质因子,我们就可以认为他是一个符合要求的质数。因为据 \(\text{deadX}\) 神仙说在 \(2\times 10^5\) 的范围内质数密度大约是 \(\dfrac{1}{10}\) ,然后大于一半的数量就大约是 \(10^5\times \dfrac{1}{10}\times \dfrac{1}{2}=500\) ,那么 \(5000\) 对数能覆盖 \(10000\) 个数,覆盖到的概率就很大了。

\(code\)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <ctime>
#define FUP(i,x,y) for(int i=(x);i<=(y);i++)
#define FDW(i,x,y) for(int i=(x);i>=(y);i--)
#define FED(i,x) for(int i=head[x];i;i=ed[i].nxt)
#define pr pair<int,int>
#define mkp(a,b) make_pair(a,b)
#define fi first
#define se second
#define MAXN 200010
#define INF 0x3f3f3f3f
#define LLINF 0x3f3f3f3f3f3f3f3f
#define eps 1e-9
#define MOD 1000000007
#define ll long long
#define db double
using namespace std;
ll read()
{
	ll w=0,flg=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-'){flg=-1;}ch=getchar();}
	while(ch<='9'&&ch>='0'){w=w*10+ch-'0',ch=getchar();}
	return w*flg;
}
int n;
ll re[MAXN];
int crand(int x){return (ll)rand()%x*rand()%x+1;}
ll getlcm(int x,int y)
{
	printf("? %d %d\n",x,y);
	fflush(stdout);
	return read();
}
void print()
{
	putchar('!');
	FUP(i,1,n) printf(" %lld",re[i]);
	puts("");
	fflush(stdout);
}
int prm[MAXN],prnum;
bool is[MAXN];
void sieve()
{
	FUP(i,2,2e5)
	{
		if(!is[i]) prm[++prnum]=i;
		FUP(j,1,prnum)
		{
			if(i*prm[j]>2e5) break;
			is[i*prm[j]]=true;
			if(!(i%prm[j])) break;
		}
	}
}
int T;
namespace solve1{
	struct node{
		ll lcm;
		pr pos;
	}p[MAXN];
	ll mk[110][110];
	bool vis[110];
	bool cmp(node x,node y){return x.lcm>y.lcm;}
	void work()
	{
		memset(vis,0,sizeof(vis));
		int pcnt=0;
		FUP(i,1,n)
		{
			FUP(j,i+1,n)
			{
				p[++pcnt].lcm=getlcm(i,j);
				p[pcnt].pos.fi=i,p[pcnt].pos.se=j;
				mk[i][j]=mk[j][i]=p[pcnt].lcm;
			}
		}
		sort(p+1,p+pcnt+1,cmp);
		ll r=sqrt((db)p[1].lcm)+1;
		int askpos=crand(n),rpos;
		while(askpos==p[1].pos.fi||askpos==p[1].pos.se) askpos=crand(n);
		if(getlcm(askpos,p[1].pos.fi)%r==0) rpos=p[1].pos.fi;
		else rpos=p[1].pos.se;
		//printf("fi=%d se=%d askpos=%d rpos=%d r=%d\n",p[1].pos.fi,p[1].pos.se,askpos,rpos,r);
		FDW(i,n,1)
		{
			ll w1=r-(n-i);
			ll w2=w1*(w1-1);
			vis[rpos]=true,re[rpos]=w1;
			//printf("rpos=%d w1=%lld w2=%lld\n",rpos,w1,w2);
			FUP(j,1,n)
			{
				if(vis[j]) continue;
				//printf("i=%d j=%d mk=%lld\n",i,j,mk[i][j]);
				if(mk[rpos][j]==w2)
				{
					rpos=j;
					break;
				}
			}
		}
		print();
	}
}
namespace solve2{
	ll rew;
	ll fenjie(ll x)
	{
		FDW(i,prnum,1)
		{
			if(prm[i]<=rew) return 1;
			//printf("prm[%d]=%d rew=%lld\n",i,prm[i],rew);
			if(x%prm[i]==0) return prm[i];
		}
		return 1;
	}
	int pl[MAXN];
	void work()
	{
		rew=0;
		FUP(i,1,n) pl[i]=i;
		random_shuffle(pl+1,pl+n+1);
		if(pl[n]==n) pl[n+1]=1;
		else pl[n+1]=n;
		int p1=0,p2=0;
		for(int i=1;i<=min(9999,n);i+=2)
		{
			ll w=getlcm(pl[i],pl[i+1]);
			ll fj=fenjie(w);
			rew=max(rew,fj);
			//printf("w=%lld rew=%lld fj=%lld\n",w,rew,fj);
			if(fj==rew) p1=pl[i],p2=pl[i+1];
		}
		int askpos=crand(n);
		//printf("askpos=%d\n",askpos);
		while(askpos==p1||askpos==p2) askpos=crand(n);
		int pos;
		if(getlcm(askpos,p1)%rew==0) pos=p1;
		else pos=p2;
		re[pos]=rew;
		FUP(i,1,n)
		{
			if(i==pos) continue;
			re[i]=getlcm(pos,i)/rew;
		}
		print();
	}
}
void solve()
{
	n=read();
	if(n<=100) solve1::work();
	else solve2::work();
}
int main(){
	srand((ll)time(NULL));
	sieve();
	T=read();
	while(T--) solve();
	return 0;
}
posted @ 2021-08-28 23:27  Pbri  阅读(54)  评论(0编辑  收藏  举报