Codeforces Round #749 (Div. 1 + Div. 2, based on Technocup 2022 Elimination Round 1)

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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值