Codeforces Round #749 (Div. 1 + Div. 2, based on Technocup 2022 Elimination Round 1) ABCD解题报告

A. Windblume Ode

A. Windblume Ode

题意:给定一个a数组,从中挑出尽可能多的数,使得这些数相加是合数。

解析:若a1+a2+…+an 为合数,则输出整个a数组,否则遍历1-n,删去其中的一个数,若剩下的数字为合数,则直接输出。可以证明答案个数一定>=n-1

#include <bits/stdc++.h>
#include<ext/rope>
#define pb push_back
#define debug(x) cerr<<#x<<'='<<x<<'\n'
#define debugg(x,y) cerr<<#x<<'='<<x<<','<<#y<<'='<<y<<'\n' 
#define FOR(a,b,c) for(int a=(b),a##_end=(c);a<=a##_end;++a)
#define ROF(a,b,c) for(int a=(b),a##_end=(c);a>=a##_end;--a)
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
using namespace __gnu_cxx;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 200010 ,M = 1000010,mod = 998244353;
ll qmi(ll,ll);
template<typename T>inline bool chkmin(T &x,const T &y){return y<x?x=y,1:0;}
template<typename T>inline bool chkmax(T &x,const T &y){return x<y?x=y,1:0;}
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}
int n,m,d;
int a[N];
bool isp(ll x)
{
	if(x<=2) return x==2;
	int s = sqrt(x);
	for(int i=2;i<=s;i++)
		if(x%i==0)
			return 0;
	return 1;
	
}
signed main()
{
	int cas;read(cas);
	while(cas--)
	{
		read(n);
		ll sum  = 0;
		for(int i=1;i<=n;i++) read(a[i]),sum+=a[i];
		if(!isp(sum))
		{
			cout<<n<<'\n';
			for(int i=1;i<=n;i++)
				cout<<i<<' ';
			puts("");
		}
		else
		{
			cout<<n-1<<'\n';
			for(int i=1;i<=n;i++)
			{
				if(!isp(sum-a[i]))
				{
					for(int j=1;j<=n;j++)
						if(j!=i)
							cout<<j<<' ';
					
					break;
				}
			}
			puts("");
		}
	}    
    return 0;
}

ll qmi(ll a,ll b) {ll res=1;a%=mod;  for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}





B. Omkar and Heavenly Tree

题意:构造一颗有n个节点的树,并且满足q个询问,每个询问给出了 a,b,c 代表a到c的简单路径中不能包含b。

解析:由于m<n 所以b必然不会包括所有的节点,随机找到一个节点(不是b) 然后其他节点都连向该节点即可

#include <bits/stdc++.h>
#include<ext/rope>
#define pb push_back
#define debug(x) cerr<<#x<<'='<<x<<'\n'
#define debugg(x,y) cerr<<#x<<'='<<x<<','<<#y<<'='<<y<<'\n' 
#define FOR(a,b,c) for(int a=(b),a##_end=(c);a<=a##_end;++a)
#define ROF(a,b,c) for(int a=(b),a##_end=(c);a>=a##_end;--a)
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
using namespace __gnu_cxx;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 200010 ,M = 1000010,mod = 998244353;
ll qmi(ll,ll);
template<typename T>inline bool chkmin(T &x,const T &y){return y<x?x=y,1:0;}
template<typename T>inline bool chkmax(T &x,const T &y){return x<y?x=y,1:0;}
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}
int n,m,d;
int a[N],b[N],c[N];
int ans[N],mp[N],vis[N];
signed main()
{
	int cas;read(cas);
	while(cas--)
	{
		read(n);read(m);
		for(int i=1;i<=n;i++) ans[i] = i,mp[i] =vis[i]= 0;
		for(int i=1;i<=m;i++) {
			read(a[i]),read(b[i]),read(c[i]);
			mp[b[i]] = 1;
		}
		int pos;
		for(int i=1;i<=n;i++)
		{
			if(!mp[i])
			{
				pos = i;
				break;
			}
		}
		for(int i=1;i<=n;i++)
		{
			if(i!=pos)
				printf("%d %d\n",pos,i);
		}
		
	}    
    return 0;
}

ll qmi(ll a,ll b) {ll res=1;a%=mod;  for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}

C. Omkar and Determination

题意:给定一个nm的网格,格子上是X代表该网格是满的,格子上是.代表该格子是空的。 倘若从能从一个格子向左或者向上走,再仅仅通过空格子的情况下(不为’X’),能走出边界,则称该格子是合适的(E),否则为(N)。 给定m组询问,每组询问包含两个整数x1,x2,代表仅取x1-x2列的网格,给出这些列格子的合适情况(每个格子是E或N),问能否仅通过合适情况推出这些格子是满的还是空的(‘X’或’.’)

解析:当且仅当出现下列情况时,满与空无法判断

?X?
X??
???

即X出现在对角线上连续出现,若仅仅知道合适与不合适的情况,上图的第二列是无法完全推出的。(第二行第二列可以是X也可以是.)
因此,只要给定的x1-x2列之间没有这种情况,即为YES,用前缀和可以轻松解决

#include <bits/stdc++.h>
#include<ext/rope>
#define pb push_back
#define debug(x) cerr<<#x<<'='<<x<<'\n'
#define debugg(x,y) cerr<<#x<<'='<<x<<','<<#y<<'='<<y<<'\n' 
#define FOR(a,b,c) for(int a=(b),a##_end=(c);a<=a##_end;++a)
#define ROF(a,b,c) for(int a=(b),a##_end=(c);a>=a##_end;--a)
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
using namespace __gnu_cxx;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 1000010 ,M = 1000010,mod = 998244353;
ll qmi(ll,ll);
template<typename T>inline bool chkmin(T &x,const T &y){return y<x?x=y,1:0;}
template<typename T>inline bool chkmax(T &x,const T &y){return x<y?x=y,1:0;}
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}
int n,m,d;
int a[N];
string s[N]; 
signed main()
{
	int cas=1;;
	while(cas--)
	{
		read(n),read(m);	
		vector<int> sum(m);
		for(int i=0;i<n;i++)
			cin>>s[i];
		for(int i=0;i<n-1;i++)
			for(int j=0;j<m-1;j++)
			{
				if(s[i+1][j]=='X'&&s[i][j+1]=='X')
					sum[j+1]++;
			}
		for(int i=1;i<m;i++) sum[i] += sum[i-1];
		int q;cin>>q;
		while(q--)
		{
			int a,b;read(a),read(b);
			--a,--b;
			puts(sum[a]==sum[b]?"YES":"NO");
		}
	}    
    return 0;
}

ll qmi(ll a,ll b) {ll res=1;a%=mod;  for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}





D. Omkar and the Meaning of Life

交互题:给定一个n,让我们通过<=2n次询问,让我们猜出题目中的排列p。 每次询问给出一个长度为n的a数组,交互系统会自动算出一个s数组,si = pi+ai ,然后返回一个下标k(下标k代表s数组中出现两次或以上的数字的最小下标)

解析:我们先通过n-1次询问计算出排列p中p[n]的值。首先假设p[n] = 1,由于a数组>=1,所以在这n-1次询问中将an调为1。在第i次询问中,a的其他值调为i+1;
正是下面这个意思:

ans[n] = 1;
FOR(i,2,n)
		{
			printf("? ");
			for(int j=1;j<n;j++)
				printf("%d ",i);
			printf("1\n");
			int k;cin>>k;
			if(k)
				ans[n]++;
			else break;
		}

对于每个询问i,倘若能够找出一个k,那么p[n]++ ,所以p[n]的值即为能找到k的的询问个数+1。这应该很好理解,毕竟p中的1-p[n]-1这些数一定可以为某次询问得到一个k。

计算出p[n] 后,我们可以直接通过p[n]的值找到1-n (不包括p[n])在排列中的位置。倘若我们要找1 那么将a1-an-1 设为n,an 设为1 则返回的k即为1的位置,更一般的 倘若我们要找t的位置,将a1-an-1设为n-t+1 ,an设为1,返回的k即为t的位置。
然后问题就解决了

#include <bits/stdc++.h>
#include<ext/rope>
#define pb push_back
#define debug(x) cerr<<#x<<'='<<x<<'\n'
#define debugg(x,y) cerr<<#x<<'='<<x<<','<<#y<<'='<<y<<'\n' 
#define FOR(a,b,c) for(int a=(b),a##_end=(c);a<=a##_end;++a)
#define ROF(a,b,c) for(int a=(b),a##_end=(c);a>=a##_end;--a)
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
using namespace __gnu_cxx;
typedef long long ll;
typedef pair<int,int> PII;
const int N = 200010 ,M = 1000010,mod = 998244353;
ll qmi(ll,ll);
template<typename T>inline bool chkmin(T &x,const T &y){return y<x?x=y,1:0;}
template<typename T>inline bool chkmax(T &x,const T &y){return x<y?x=y,1:0;}
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}
int n,m,d;
int ans[N],a[N];
signed main()
{
	int cas=1;
	while(cas--)
	{
		read(n);
		memset(ans,0,sizeof(int)*(n+5));
		ans[n] = 1;
		FOR(i,2,n)
		{
			printf("? ");
			for(int j=1;j<n;j++)
				printf("%d ",i);
			printf("1\n");
			int k;cin>>k;
			if(k)
				ans[n]++;
			else break;
		}
		FOR(i,1,n)
		{
			if(i==ans[n]) continue;
			//find(i)
			printf("? ");
			for(int j=1;j<n;j++)
				printf("%d ",n-i+1);
			printf("%d\n",n+1-ans[n]); 
			int x;cin>>x;
			ans[x] = i;
		}
		printf("! ");
		for(int i=1;i<=n;i++)
			printf("%d ",ans[i]);
	}    
    return 0;
}

ll qmi(ll a,ll b) {ll res=1;a%=mod;  for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}




  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值