sduwh xcpc选拔赛(2)

A 《签到题》

开局被这个签到题搞心态了 md

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
int main(){
	int n,x,c,ans=0;
	cin>>n>>x>>c;
	for(int i=1;i<=n;i++){
		int xx;
		cin>>xx;
		if(xx<c)continue;
		if(abs(xx-x)<=3)ans++;
	} 
    if(x<c)cout<<"0"<<endl;
    else 
	cout<<ans<<endl;
     return 0;
}

F 《数金币》

分析:

开始以为是中国剩余定理 打了一遍 才发现数据太大了

发现只需要枚举一下就好了了 注意从0开始

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
const int maxn=1e3+5;
ll a[maxn],b[maxn];
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)scanf("%lld %lld",&a[i],&b[i]);
	for(int i=1;i<=100000;i++){
		int pd=1;
		for(int j=1;j<=n;j++)
			if((i%a[j])!=b[j]){
				pd=0;
				break;
			}
		if(pd){
			cout<<i;
			return 0;
		}
	}
	cout<<"SO RICH!";
     return 0;
}

D 《爆金币》

分析:

开始以为是什么很高级的题目

结果其实就是排序

队员的值很小 桶排序 队长的人数少但是数值大 直接排序

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
const int maxn=1e3+5;
const int maxm=1e5+5;
int n,k,cnt;
int Q[maxn],res[maxm];
int main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		int xx,yy;
		scanf("%d%d",&xx,&yy);
		for(int j=yy;j>=1;j--){
			int p=xx%j;
			Q[p]++;
			xx-=p;
		}
		if(xx<100)
		Q[xx]++;
		else res[++cnt]=xx;
	}
	if(k<=cnt){
		sort(res+1,res+1+cnt);
		cout<<res[cnt-k+1];
	return 0;
	}
	int sum=0;
	k-=cnt;
	for(int i=99;i>=0;i--){
		if(sum+Q[i]>=k){
			cout<<i<<endl;
			return 0;
		}
		sum+=Q[i];
	}
	return 0;
}

B 《挖金币》

分析:

很好想到是并查集 但是比赛不知道怎么连边

1 对于同行点的 所在列 合并为一堆(两列能共享剩下的点) ans的一部分即为堆数-1

2 对于剩下没有点的行 每行只需要一个点即可

ans=空行+堆数-1

#include <bits/stdc++.h>
using namespace std;
template <typename T>
inline T next() {
    T x;
    cin >> x;
    return x;
}
void untie() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
using LL = long long;
void solve() {
    int n = next<int>();
    int m = next<int>();
    int k = next<int>();
    vector<int> mark(n + 1);
    vector<int> fa(m + 1);
    for (int i = 1; i <= m; i++) {
        fa[i] = i;
    }
    function<int(int)> getf = [&](int x) -> int {
        return fa[x] == x ? x : (fa[x] = getf(fa[x]));
    };
    for (int i = 1; i <= k; i++) {
        int x = next<int>();
        int y = next<int>();
        if (mark[x]) {
            fa[getf(y)] = getf(mark[x]);
        }
        mark[x] = y;
    }
    int ans = -1;
    for (int i = 1; i <= m; i++) {
        ans += fa[i] == i;
    }
    for (int i = 1; i <= n; i++) {
        ans += mark[i] == 0;
    }
    cout << ans << '\n';
}
int main() {
    untie();
    int T = 1; // next<int>();
    while (T--) {
        solve();
    }
    return 0;
}

E 《矩阵填数》

分析:

很容易想到奇数和偶数分为两部分 关键点在于分界线不好处理

对于n=3,4,5手动处理

对于n>=6 3的奇数倍和偶数倍个数都>=n

将3的奇数倍和偶数倍分别组合

比赛的时候sb了 没有想到倍数来组合非质数

#include <bits/stdc++.h>
using namespace std;
 
int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
	int n;
	cin >> n;
	vector<vector<int>> A(n, vector<int>(n));
	if(n == 3) {
		A[0] = {5, 9, 1};
		A[1] = {3, 7, 8};
		A[2] = {6, 2, 4};
	}
	if(n == 4) {
		A[0] = { 9, 11, 13, 15};
		A[1] = { 1,  3,  5,  7};
		A[2] = { 8,  6,  4,  2};
		A[3] = {10, 12, 14, 16};
	}
	if(n == 5) {
		A[0] = { 5,  7, 11, 13, 17};
		A[1] = {19, 23, 25, 21,  1};
		A[2] = { 3,  9, 15, 24,  8};
		A[3] = { 6, 12, 18,  2,  4};
		A[4] = {10, 14, 16, 20, 22};
	}
	if(n >= 6) {
		vector<int> B;
		for(int x = 1; x <= n * n; ++ x)
		  	if(x % 2 == 1 && x % 3 != 0) 
		  		B.push_back(x);
		for(int x = 1; x <= n * n; ++ x)
			if(x % 2 == 1 && x % 3 == 0) 
				B.push_back(x);
		for(int x = 1; x <= n * n; ++ x)
			if(x % 2 == 0 && x % 3 == 0) 
		  		B.push_back(x);
		for(int x = 1; x <= n * n; ++ x)
			if(x % 2 == 0 && x % 3 != 0) 
		  		B.push_back(x);
		for(int i = 0; i < n; ++ i)
			for(int j = 0; j < n; ++ j) 
		  		A[i][j] = B[n * i + j];
	}
	for(int i = 0; i < n; ++ i) 
		for(int j = 0; j < n; ++ j) 
	  		cout << A[i][j] << " \n"[j == n - 1];
	return 0;
}

C 子序列

分析:
一道非常好的题目

已知pi 的倍数的位置 可以为q[i1] q[i2]....q[ik]

从p1顺序处理到pn

对于每个pi 选择一个q[i] 使得递增 最终使得长度最大

不难想到最长上升子序列问题

代码写的很清楚

 #include <bits/stdc++.h>
using namespace std;
template <typename T>
inline T next() {
    T x;
    cin >> x;
    return x;
}
void untie() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
using LL = long long;
void solve() {
    int n = next<int>();
    vector<int> a(n + 1);
    vector<int> b(n + 1); 
        a[i] = next<int>();
    }
    for (int i = 1; i <= n; i++) {
        b[next<int>()] = i;
    }
    vector<int> atree(n + 1);
    auto add = [&](int x, int v) -> void {
        for (int i = x; i <= n; i += i & -i) {
            atree[i] = max(atree[i], v);
        }
    };
    auto query = [&](int x) -> int {
        int ans = 0;
        for (int i = x; i; i -= i & -i) {
            ans = max(ans, atree[i]);
        }
        return ans;
    };
    for (int i = 1; i <= n; i++) {
        set<pair<int, int>> op;
        for (int j = a[i]; j <= n; j += a[i]) {
            int p = b[j];
            int v = query(p - 1) + 1;
            op.insert(make_pair(p, v));
        }
        for (auto pv : op) {
            add(pv.first, pv.second);
        }
    }
    cout << query(n) << '\n';
}
int main() {
    untie();
    int T = 1; // next<int>();
    while (T--) {
        solve();
    }
    return 0;
}
posted @ 2022-10-19 15:27  wzx_believer  阅读(24)  评论(0编辑  收藏  举报