【CF套题】 Educational Codeforces Round 58

【前言】
组队CF之帮wyl上橙,我和sc打小号上紫。
结果sc成功FST两题,wyl成功skipped。
我的小号幸存了qwq。

【题目】
原题地址

A.Minimum Integer

特判一下 d d d是不是在 [ l , r ] [l,r] [l,r]中,如果是那么答案就是 x ∗ ( r x + 1 ) x*(\frac r x +1) x(xr+1)

#include
#define mkp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;

typedef double db;
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f;

int read()
{
	int ret=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return f?ret:-ret;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("A.in","r",stdin);
	freopen("A.out","w",stdout);
#endif
	int T=read();
	while(T--)
	{
		int l=read(),r=read(),x=read();
		if(x<l || x>r){printf("%d\n",x);}
		else printf("%d\n",(r/x+1)*x);
	}
	return 0;
}

B.Accordion

模拟。

#include
#define mkp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;

typedef double db;
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f,N=1e6+10;
int p[10],ans;
char s[N];

int read()
{
	int ret=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return f?ret:-ret;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("B.in","r",stdin);
	freopen("B.out","w",stdout);
#endif
	scanf("%s",s);;int n=strlen(s);
	memset(p,-1,sizeof(p));
	for(int i=0;i<n;++i) if(s[i]=='[') {p[1]=i;break;}
	for(int i=n-1;~i;--i) if(s[i]==']') {p[2]=i;break;}
	if(p[1]>p[2] || p[1]==-1 || p[2]==-1){puts("-1");return 0;}
	for(int i=p[1]+1;i<p[2];++i) if(s[i]==':'){p[3]=i;break;}
	for(int i=p[2]-1;i>p[1];--i) if(s[i]==':'){p[4]=i;break;}
	if(p[3]==-1 || p[4]==-1 || p[3]==p[4]) {puts("-1");return 0;}
	for(int i=p[3]+1;i<p[4];++i) if(s[i]=='|') ++ans;
	printf("%d\n",ans+4);

	return 0;
}

C.Division and Union

按左端点排序,判断和上一条线段位置关系分组。
若一条线段被另一条包含在过程中可以判掉。

#include
#define mkp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;

typedef double db;
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f,N=1e5+10;
int n,bl[N];

int read()
{
	int ret=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return f?ret:-ret;
}

struct seg
{
	int l,r,id;
	seg(int _l=0,int _r=0,int _id=0):l(_l),r(_r),id(_id){}
}a[N];
bool cmp(const seg&a,const seg&b)
{
	return a.l<b.l || (a.l==b.l && a.r<b.r);
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("C.in","r",stdin);
	freopen("C.out","w",stdout);
#endif
	int T=read();
	while(T--)
	{
		n=read();
		for(int i=1;i<=n;++i) a[i].l=read(),a[i].r=read(),a[i].id=i;
		sort(a+1,a+n+1,cmp);
		for(int i=1;i<=n;++i) bl[i]=-1;
		int las=0;
		for(int i=1;i<=n;++i) 
		{
			//cerr<
			if(a[i].l>=a[las].l && a[i].r<=a[las].r) {bl[a[i].id]=bl[a[las].id];continue;}
			if(a[i].l>a[las].r) bl[a[i].id]=bl[a[las].id]^1;
			else bl[a[i].id]=bl[a[las].id];
			las=i;
		}
		bool fg=0;
		for(int i=1;i<=n;++i) if(bl[a[i].id]==0){fg=1;break;}
		if(!fg){puts("-1");}
		else {for(int i=1;i<=n;++i)printf("%d ",bl[i]+1);puts("");}
	}

	return 0;
}

D.GCD Counting

枚举质因子, bfs \text{bfs} bfs直径。注意多余的边和点什么的不要经过。

#include
#define mkp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;

typedef double db;
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f,N=2e5+10;
int tot,n,pnum,rt,ans;
int bo[N],head[N],pri[N],dis[N],a[N];
map<int,bool>mp;
queue<int>q;

int read()
{
	int ret=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return f?ret:-ret;
}

struct Tway{int v,w,nex;}e[N<<1];
void add(int u,int v,int w)
{
	e[++tot]=(Tway){v,w,head[u]};head[u]=tot;
	e[++tot]=(Tway){u,w,head[v]};head[v]=tot;
}
int gcd(int x,int y){return y?gcd(y,x%y):x;}

void init()
{
	for(int i=2;i<N;++i)
	{
		if(!bo[i]) pri[++pnum]=i;
		for(int j=1;j<=pnum && i*pri[j]<N;++j)
		{
			bo[i*pri[j]]=1;
			if(!(i%pri[j])) break;
		}
	}
}
int bfs(int x,int p)
{
	q.push(x);mp.clear();mp[x]=1;dis[x]=1;
	int res=1;
	while(!q.empty())
	{
		int u=q.front();q.pop();
		for(int i=head[u];i;i=e[i].nex)
		{
			int v=e[i].v,w=e[i].w;
			//cerr<
			if(mp[v] || gcd(p,w)==1) continue; 
			
			dis[v]=dis[u]+1;rt=v;res=dis[v];mp[v]=1;
		}
	}
	return res;
}

void findtree(int x,int p)
{
	//cerr<
	rt=0;bfs(x,p);
	int res=bfs(rt,p);
	ans=max(ans,res);
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("D.in","r",stdin);
	freopen("D.out","w",stdout);
#endif
	n=read();init();
	for(int i=1;i<=n;++i) a[i]=read();
	for(int i=1;i<n;++i)
	{
		int u=read(),v=read();
		add(u,v,gcd(a[u],a[v]));
	}
	for(int p=1;p<=pnum;++p)
	{
		memset(dis,0,sizeof(dis));
		for(int i=1;i<=n;++i) if(!dis[i] && gcd(a[i],pri[p])>1) findtree(i,pri[p]);
	}
	printf("%d\n",ans);
	return 0;
}

E.Polycarp’s New Job

将短边放前面,记录最大值判断一下。

#include
#define mkp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;

typedef double db;
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f;
int m,mxx,mxy;

int read()
{
	int ret=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return f?ret:-ret;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("E.in","r",stdin);
	freopen("E.out","w",stdout);
#endif
	m=read();
	while(m--)
	{
		char op[2];int x,y;
		scanf("%s%d%d",op,&x,&y);
		if(x>y) swap(x,y);
		if(op[0]=='+') mxx=max(mxx,x),mxy=max(mxy,y);
		else puts((mxx<=x && mxy<=y)?"YES":"NO");
	}
	return 0;
}

F.Trucks and Cities

我们设 f i , j , k f_{i,j,k} fi,j,k表示从 i i i城市到 j j j城市,加油 k k k次,需要跑的最远一段路程。
显然 f i , i + 1 , 1 = a i + 1 − a i f_{i,i+1,1}=a_{i+1}-a_i fi,i+1,1=ai+1ai
若我们固定了 i i i,当 k k k越大,最后一次加油的位置一定单调右移。
于是我们可以枚举这一阶段最后一次加油是在什么地方,随着这个位置右移,上一阶段最后一次加油位置一定也右移。
这个东西相当于将行程拆成了两部分 i − > j , j − > k i->j,j->k i>j,j>k
转移也没什么好说的。
复杂度就是 O ( n 3 + m ) O(n^3+m) O(n3+m)的了。

#include
#define mkp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;

typedef double db;
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f,N=405;
int n,m,a[N],f[N][N][N];
ll ans;

int read()
{
	int ret=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return f?ret:-ret;
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("F.in","r",stdin);
	freopen("F.out","w",stdout);
#endif
	n=read();m=read();
	for(int i=1;i<=n;++i) a[i]=read();
	for(int i=1;i<n;++i) 
	{
		for(int j=i+1;j<=n;++j) f[i][j][1]=a[j]-a[i];
		for(int t=2;t+i<=n;++t)
		{
			int las=i+t-1;
			for(int j=i+t;j<=n;++j)
			{
				while(las+1<j && max(f[i][las][t-1],a[j]-a[las])>max(f[i][las+1][t-1],a[j]-a[las+1])) ++las;
				f[i][j][t]=max(f[i][las][t-1],a[j]-a[las]);
			}
		}
	}
	for(int i=1;i<=m;++i) 
	{
		int s=read(),t=read(),c=read(),r=read();
		ans=max(ans,(ll)f[s][t][min(t-s,r+1)]*c);
	}
	printf("%lld\n",ans);
	return 0;
}

G.(Zero XOR Subset)-less

这是一道线性基裸题。
首先无解当且仅当所有数异或为0,否则显然可以构造出解。
我们只需要先让所有数先做一个前缀异或,然后按顺序插入线性基即可。
最后线性基中的基底个数就是答案。

#include
#define mkp make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;

typedef double db;
typedef long long ll;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f,N=3e5+10;
int n,a[N];

int read()
{
	int ret=0,f=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=0;c=getchar();}
	while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
	return f?ret:-ret;
}
void getfail(){puts("-1");exit(0);}

struct LinearBase
{
	int ans,b[100];
	void insert(int x)
	{
		int i,j;
		for(i=30;~i;i--) if(x>>i&1)
		{
			if(b[i]) x^=b[i];
			else break;
		}
		if(!x) return;
		b[i]=x;++ans;
		for(j=i-1;~j;j--) if(b[i]>>j&1) b[i]^=b[j];
		for(j=i+1;j<31;j++) if(b[j]>>i&1) b[j]^=b[i];
	}
}T;

int main()
{
#ifndef ONLINE_JUDGE
	freopen("F.in","r",stdin);
	freopen("F.out","w",stdout);
#endif
	n=read();
	for(int i=0;i<n;++i) a[i]=read();
	for(int i=1;i<n;++i) a[i]^=a[i-1];
	if(!a[n-1])getfail();
	for(int i=0;i<n;++i) T.insert(a[i]);
	printf("%d\n",T.ans);
	return 0;
}

你可能感兴趣的:(codeforces)