Codeforces Round #749 (Div. 1 + Div. 2, based on Technocup 2022 Elimination Round 1)
A
题目
互不相同的n个数字,求它们的最大的一个子集合,使它们的和是一个合数 , 保证n>=3
思路
1. 除2外的质数都是一个奇数
2. 一个奇数减去一个比它小的奇数,一定可以得到一个偶数
- n>=3 , 所以答案只有n或者n-1两种可能, 因为 质数除2都是奇数,又因为给的所有数字都是不同的且它们的总数都大于二,所以加出来的和一定比2大。
- 有这样的基础,如果这个和是个质数,只要再减去一个奇数就可以变成一个偶数了。
AC代码
#include <bits/stdc++.h>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define debug(x) cout<<"> "<< x<<endl;
#define ull unsigned long long
#define endl '\n'
#define lowbit(x) x&-x
//#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N =10 + 1e5 ,mod=1e9 + 7;
set<int>p;
bool isp(int n){
for(int i=2;i<=sqrt(n);i++)
if(n%i == 0) return 0;
return 1;
}
void getp(){
for(int i=2;i<=20100;i++){
if(isp(i))
p.insert(i);
}
}
void solve()
{
int sum = 0;
int n;
cin>>n;
vector<PII>a(n);
for(int i=0;i<n;i++){
int t;
cin>>t;
sum += t;
a[i] = {t,i};
}
int tot = n;
sort(a.begin(),a.end());
while(isp(sum)){
for(int i=0;i<n;i++){
if(a[i].second == -1) continue;
if(p.count(sum - a[i].first) == 0){
a[i].second = -1;
sum -= a[i].first;
tot --;
break;
}
}
}
cout << tot << endl;
for(int i=0;i<n;i++){
if(a[i].second != -1)
cout<<1+a[i].second<<' ';
}
cout<<endl;
}
signed main()
{
ios::sync_with_stdio();cin.tie();cout.tie();
getp();
// cout<<p.size()<<endl;
// for(auto it:p) cout<<it<<' ';
// // cout<<endl;
int T;cin>>T;
while(T--)
solve();
return 0;
}
B
### 题目
构造一棵有约束的树,给定m个约束,表示两个节点之间不可以紧挨着某个节点 ,找构造方案
思路
- 显然,只要找到一个未被约束的中继点,以他为根建立一颗深度为2的树即可,
AC代码
#include <bits/stdc++.h>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define debug(x) cout<<"> "<< x<<endl;
#define ull unsigned long long
#define endl '\n'
#define lowbit(x) x&-x
//#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N =10 + 1e5 ,mod=1e9 + 7;
int arr[N];
bool vis[N];
void solve()
{
memset(vis,0,sizeof vis);
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) arr[i] = i;
for(int i=0;i<m;i++){
int a,b,c;
cin>>a>>b>>c;
vis[b] = 1;
}
int r;
for(int i=1;i<=n;i++){
if(!vis[i]){
r = arr[i];
break;
}
}
for(int i=1;i<=n;i++){
if(vis[i] == 0 && arr[i] != r)
vis[i] = 1;
}
for(int i=1;i<=n;i++){
if(vis[i])
cout << r << ' '<< arr[i] <<endl;
// cout << arr[i] << endl;
}
}
signed main()
{
ios::sync_with_stdio();cin.tie();cout.tie();
int T;cin>>T;
while(T--)
solve();
return 0;
}
/*
2
7 2
1 2 3
3 4 5
5 6 7
6 5 4
5 3
1 2 3
3 2 4
3 2 5
*/
C
题目
给一个图,一个人可以从任何未被堵住的地方,向上或者向左走,如果这个起点可以从左边界或者上边界出去,那么这个点就是可以出去的,反之这个点不可以出去,问对某个地图来说,是否可以通过人的是否可通过使得这个图唯一确定。
思路
- 把点分成两类,如果有一个点既可以是可通过的又可以被堵上,那么只要有这个点,这个图就是不唯一的。
- 很容易注意到对于每个地图的第一行和第一列,总是可以唯一确定,所以只要判断内部的点是否唯一即可
- 为降低时间复杂度,我们可以预处理出一个二维前缀和,显然如果有一个点的左边和上边都被堵上,那么这个点是啥,都是无法通过的,也就无法唯一确定下来。 那么对于这样的点标记为1,唯一确定的点标记为0即可。
- 每次查询一段开区间的前缀和即可。
AC代码
#include <bits/stdc++.h>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define ll long long
#define linf 0x3f3f3f3f3f3f3f3f
#define debug(x) cout<<"> "<< x<<endl;
#define ull unsigned long long
#define endl '\n'
#define lowbit(x) x&-x
//#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N =10 + 1e5 ,mod=1e9 + 7;
int n,m;
void solve()
{
cin>>n>>m;
int g[n][m];
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
char c;
cin >> c;
if(c == 'X') g[i][j] = 1;
else g[i][j] = 0;
}
int pre[n][m];
memset(pre,0,sizeof pre);
for(int i=1;i<n;i++){
for(int j=1;j<m;j++){
if(g[i-1][j] && g[i][j-1]){
pre[i][j] = pre[i-1][j] + pre[i][j-1] - pre[i-1][j-1] + 1;
}else{
pre[i][j] = pre[i-1][j] + pre[i][j-1] -pre[i-1][j-1];
}
}
}
// for(int i=0;i<n;i++,puts(""))
// for(int j=0;j<m;j++)
// cout<<pre[i][j]<<' ';
int q;
cin>>q;
while(q--){
int l,r;
cin>>l>>r;
l--,r--;
int ok = pre[n - 1][r] - pre[0][r] - pre[n - 1][l] +pre[0][l];
// cout<<pre[n - 1][r]<<' '<<pre[0][r]<<' '<<pre[n - 1][l]<<' '<<pre[0][l]<<endl;
if(ok) puts("NO");
else puts("YES");
}
}
signed main()
{
ios::sync_with_stdio();cin.tie();cout.tie();
solve();
return 0;
}
D
题目
交互题,每次可以构造一个序列加上目标序列,如果加过的序列后有相同元素,返回最前面的,如果没有返回0,最大2n次查询
思路
- 每次可以得到一个靠前的信息, 核心思路可以确定,先求出最后的一个以他为基准,查找所有前面的元素即可
- 查询时应该分类元素,分为比最后大的和比最后小的,查询中的过程中要记录和最后的一个差距d
AC代码
#include <bits/stdc++.h>
#define yes puts("yes");
#define inf 0x3f3f3f3f
#define linf 0x3f3f3f3f3f3f3f3f
#define ll long long
#define ull unsigned long long
#define debug(x) cout<<"> "<< x<<endl;
// #define endl '\n'
#define lowbit(x) x&-x
//#define int long long
using namespace std;
typedef pair<int,int> PII;
const int N =10 + 1e5, mod = 1e9 + 7;
void solve()
{
int n;
cin>>n;
int cnt = 0;
vector<int>ans(n+1);
{
for(int i=0;i<=n;i++) ans[i] = 0;
}
for(int i=2;i<=n;i++){
cout<<"?";
for(int j=1;j<n;j++) cout << " 1";
cout << " "<< i << endl;
int res ;
cin>>res;
cnt += (res == 0);
if(res){
ans[res] = i - 1;
}
}
ans[n] = cnt + 1;
for(int i=1;i<n;i++){
if(ans[i]){
ans[i] += ans[n];
}
}
for(int i = 2; i <= n;i++){
cout << "?";
for(int j=1;j<n ; j++) cout << " "<< i ;
cout << " " << 1 << endl;
int res;
cin>> res;
if(res){
ans[res] = ans[n] - (i-1);
}
}
cout << "!";
for(int i=1;i<=n;i++) cout<< " " << ans[i] ;
cout << endl;
}
signed main()
{
ios::sync_with_stdio();cin.tie();cout.tie();
solve();
return 0;
}