Codeforces Round #709 (Div. 2, based on Technocup 2021 Final Round)ABCD题解

A题 每个方格破一条边即可

#include<bits/stdc++.h>
using namespace std;
int t,a,b;
int main()
{
    
    
	cin>>t;
	while(t--)
	{
    
    
		cin>>a>>b;
		cout<<a*b<<'\n';
	}
	return 0;
}

B题 对于一对 a [ i ] < a [ i + 1 ] a[i]<a[i+1] a[i]<a[i+1], c = a [ i + 1 ] − a [ i ] + k ∗ m c=a[i+1]-a[i]+k*m c=a[i+1]a[i]+km c c c a [ i + 1 ] − a [ i ] a[i+1]-a[i] a[i+1]a[i]即可,因为在模 m m m的情况下一样, c c c一旦确定, m m m也可以确定,只要判断这对 c , m c,m c,m能不能推出整个序列即可

我代码写的太繁琐了就不放了 (比赛时把所有情况都写进去了,会有重复判断的部分)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int t,n,a[N];
int main()
{
    
    
	scanf("%d",&t);
	while(t--)
	{
    
    
		scanf("%d",&n);
		int m,ma=0,c;
		bool f=0;
		for(int i=1;i<=n;i++)scanf("%d",&a[i]),ma=max(ma,a[i]);
		if(n==1||n==2)
		{
    
    
			puts("0");
			continue;
		}
		for(int i=2;i<=n;i++)
		{
    
    
			if(a[i]!=a[i-1])f=1;
		}
		if(!f)
		{
    
    
			puts("0");
			continue;
		}
		f=0;
		for(int i=1;i<n;i++)
		{
    
    
			if(a[i]>=a[i+1])f=1;
		}
		if(!f)
		{
    
    
			bool ff=0;
			for(int i=1;i<n-1;i++)
			{
    
    
				if(a[i+1]-a[i]!=a[i+2]-a[i+1])
				{
    
    
					ff=1;
					break;
				}
			}
			if(ff)puts("-1");
			else puts("0");
			continue;
		}
		f=0;
		for(int i=1;i<n;i++)
		{
    
    
			if(a[i]<=a[i+1])f=1;
		}
		if(!f)
		{
    
    
			if(!f)
			{
    
    
				bool ff=0;
				for(int i=1;i<n-1;i++)
				{
    
    
					if(a[i+1]-a[i]!=a[i+2]-a[i+1])
					{
    
    
						ff=1;
						break;
					}
				}
				if(ff)puts("-1");
				else puts("0");
				continue;
			}
		}
		f=0;
		for(int i=1;i<n;i++)
		{
    
    
			if(a[i]==a[i+1])f=1;
		}
		if(f)
		{
    
    
			puts("-1");
			continue;
		}
		for(int i=1;i<n;i++)
		{
    
    
			if(a[i]<a[i+1])
			{
    
    
				c=a[i+1]-a[i];
				break;
			}
		}
		f=0;
		if(c==-1)
		{
    
    
			puts("-1");
			continue;
		}
		for(int i=1;i<n;i++)
		{
    
    
			if(a[i]<a[i+1]&&a[i+1]-a[i]!=c)
			{
    
    
				f=1;
				break;
			}
		}
		if(f)
		{
    
    
			puts("-1");
			continue;
		}
		for(int i=1;i<n;i++)
		{
    
    
			if(a[i]>a[i+1])
			{
    
    
				m=a[i]+c-a[i+1];
				break;
			}
		}
		for(int i=1;i<n;i++)
		{
    
    
			if(a[i]>a[i+1]&&a[i]+c-a[i+1]!=m)
			{
    
    
				f=1;
				break;
			}
		}
		if(f)
		{
    
    
			puts("-1");
			continue;
		}
		if(ma>=m)puts("-1");
		else cout<<m<<' '<<c%m<<'\n';
	}
	return 0;
}

C题 只要 k = 1 k=1 k=1的情况下的 m a x ( c n t [ x ] ) < = ( m + 1 ) / 2 max(cnt[x])<=(m+1)/2 max(cnt[x])<=(m+1)/2就有解.
举个例子(不表示出k)(最坏的情况下)
2
2
2
2
1 2
1 2
1 2
显然前面4天选2,后面3天选1即可
要先把 k = 1 k=1 k=1的情况固定,在去看k>1的情况;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int t,n,m,k[N],cnt[N],ans[N];
vector<int>v[N];
int main()
{
    
    
	scanf("%d",&t);
	while(t--)
	{
    
    
		scanf("%d%d",&n,&m);
		memset(cnt,0,sizeof cnt);
		int mm=0;
		for(int i=1;i<=m;i++)v[i].clear();
		for(int i=1;i<=m;i++)
		{
    
    
			int x;
			scanf("%d",&k[i]);
			for(int j=1;j<=k[i];j++)
			{
    
    
				scanf("%d",&x);
				v[i].push_back(x);
			}
			if(k[i]==1)
			{
    
    
				cnt[x]++;
				if(mm<=cnt[x])mm=cnt[x];
			}
		}
		if(mm>(m+1)/2)
		{
    
    
			puts("NO");
			continue;
		}
		puts("YES");
		for(int i=1;i<=m;i++)
		{
    
    
			if(k[i]==1)ans[i]=v[i][0];
			else
			{
    
    
				for(int j=0;j<k[i];j++)
					if(cnt[v[i][j]]+1<=(m+1)/2)
					{
    
    
						cnt[v[i][j]]++;
						ans[i]=v[i][j];
						break;
					}
			}
		}
		for(int i=1;i<=m;i++)cout<<ans[i]<<' ';
		puts("");
	}
	return 0;
}

D题 n e [ i ] ne[i] ne[i]用来表示 i i i这个位置的下一个未被删除的元素的下标, a n s ans ans存答案,先把原数组相邻2个 g c d gcd gcd为1的2个下标存入q中,比如一个 ( x , y ) (x,y) (x,y),然后把y删了之后再判断 a [ x ] a[x] a[x] a [ n e [ y ] ] a[ne[y]] a[ne[y]] g c d gcd gcd如果是1,就把 ( x , n e [ y ] ) (x,ne[y]) (x,ne[y])存入q中,循环

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int t,n,a[N];
map<int,int>ne;
queue<pair<int,int>>q;
vector<int>ans;
int gcd(int a,int b){
    
    
    int r;
    while(b)
    {
    
    
        r=a%b;
        a=b;
        b=r;
    }
    return a;
}
int main()
{
    
    
	scanf("%d",&t);
	while(t--)
	{
    
    
		ans.clear();
		ne.clear();
		while(q.size())q.pop();
		scanf("%d",&n);
		for(int i=1;i<=n;i++)scanf("%d",&a[i]);
		for(int i=1;i<n;i++)
		{
    
    
			ne[i]=i+1;
			if(gcd(a[i],a[i+1])==1)
				q.push({
    
    i,i+1});
		}
		ne[n]=1;
		if(gcd(a[n],a[1])==1)q.push({
    
    n,1});
		while(q.size())
		{
    
    
			auto now=q.front();
			q.pop();
			int x=now.first,y=now.second;
			if(!ne.count(x))continue;
			ans.push_back(y);
			ne[x]=ne[y];
			if(gcd(a[x],a[ne[x]])==1)
				q.push({
    
    x,ne[x]});
			ne.erase(y);//一定要先判断再删,不然会出现ne为空的情况
		}
		cout<<ans.size()<<' ';
		for(int i=0;i<ans.size();i++)cout<<ans[i]<<' ';
		puts("");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_46001550/article/details/115072199