SUM-ACM天梯赛

第一次天梯赛:
B-B:孵化小鸡
题解:二进制枚举所有可能性,一个一个枚举出来,@离散数学,真值表。
题目如下:

二进制枚举代码如下

点击查看代码
#include <bits/stdc++.h>
using namespace std;

int main ()
{
	int n;
	cout<<"输入你要枚举的个数";
	cin>>n;
	for(int i=0;i<=(1<<n)-1;i++){
		int j=i;//把i化成二进制数;
		int p=0;//所有可能性的下标
		vector<int> e;//存下标的数组
		while(j)
		{
			if(j%2)
			{
				e.push_back(p);
			}
			p++;
			j/=2;
		}
		cout<<"第"<<i<<"种下标"<<"\n";
		for(int k=0;k<e.size();k++){
			cout<<e[k];
		}
		cout<<"\n";
		
	}
	return 0;
}
完整代码如下:
点击查看代码
#include <bits/stdc++.h>
#define int long long
#define MOD 1000000007
using namespace std;

int a[25],b[25],mm[25],t[105]={0},p[105]={0};;

//学会这个暴力题乱杀。

struct asmd{
	int l,r;
	int k,p;
}s[12];


int32_t main() {
	int T = 1;
	//cin >> T;
	while (T--) {
		int n,m,mn=1e9;
		cin>>n>>m;
		for(int i=1;i<=n;i++){
			cin>>a[i]>>b[i]>>mm[i];
			for(int j=a[i];j<=b[i];j++){
				if(mm[i]>t[j]){
					t[j]=mm[i];
				}
			}
		}
		for(int i=0;i<m;i++){
			cin>>s[i].l>>s[i].r>>s[i].k>>s[i].p;
		}
		for(int i=0;i<=(1<<m)-1;i++){
			int pos=0;
			vector<int>q;
			int ii=i;
			while(ii){
				if(ii%2){
					q.push_back(pos);
				}
				pos++;
				ii>>=1;
			}
			int f=1,sum=0;
			for(int j=0;j<q.size();j++){
				sum+=s[q[j]].p;
				for(int k=s[q[j]].l; k<=s[q[j]].r;k++){
					p[k]+=s[q[j]].k;
				}
			}
			for(int j=1;j<=100;j++){
				if(t[j]>p[j]){
					f=0;
					break;
				}
			}
			memset(p,0,sizeof p); //重置
			if(f){
				mn=min(mn,sum);
			}
		}
		cout<<mn<<endl;
	}
}

D-D 划分田地
题解:跟上面那道题类似,都是枚举暴力,找每种矩形的x左右两边和y上下两边然后拿剩下的点和x,y的两个值进行比较,累加
然后插入vector存储每一个不同的土豆数,然后ans++,枚举所有得出答案;

题目如下:

代码如下

点击查看代码
#include<bits/stdc++.h>

using namespace std;

using i32 = int32_t;
using i64 = long long;

#define int i64

using pii = pair<int, int>;
using vi = vector<int>;


i32 main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int n;
    cin >> n;
    vector<pii> a(n);
    for (auto &[x, y]: a) cin >> x >> y;

    set<vi> res;

    res.insert(vi());

    for (int ax = 0; ax <= 50; ax++)
        for (int bx = ax; bx <= 50; bx++)
            for (int ay = 0; ay <= 50; ay++)
                for (int by = ay; by <= 50; by++) {
                    vi s;
                    for (int k = 0; k < n; k++) {
                        if (ax <= a[k].first and a[k].first <= bx and ay <= a[k].second and a[k].second <= by)
                            s.push_back(k);
                    }
                    res.insert(s);

                }
    cout << res.size() << "\n";
    return 0;
}


I-I 找除数 题解:这道题是质数和因数分解,需要掌握线性筛和质数筛;

质数筛

https://blog.csdn.net/Bananaaay/article/details/124698131

线性筛

https://blog.csdn.net/weixin_46522531/article/details/128422821
题目如下:

代码如下

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
int prime[1000006],cnt;
bool st[1000006];
void get_prime(int n){
	for(int i=2;i<=n;i++){
		if(!st[i]){
			prime[cnt++]=i;
		}
		for(int j=0;i*prime[j]<=n;j++){
			st[i*prime[j]]=1;
			if(i%prime[j]==0)
				break;
		}
	}
}
void solve() {
	int x;
	cin >> x;
	vector<int>g;
	for (int i = 0; prime[i]<= x / prime[i] and i<cnt; ++i) {
		int dq=0;
		while (x % prime[i] == 0) {
			dq++;
			x /= prime[i];
		}
		if(dq){
			g.push_back(dq);
		}
	}
	if (x > 1)
		g.push_back(1);
	int ans=1;
	for (auto p: g) {
		ans = ans * (p+ 1);
	}
	cout<<ans<<endl;
}
int main(){
	ios::sync_with_stdio(false),cin.tie(0);
	get_prime(100000);
	int t;
	cin>>t;
	while (t--){
		solve();
	}
}


第一次天梯赛学到的暂时只有这么多,还有一些dp正在学习中,此地留空,方便到时候补dp。
J-J
最后都是零
题解:这道题我用贪心做出来了,就是找每个数中的最大值,然后减去这个数,剩下一位的时候ans++,剩下为10的时候ans+=2;

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long

int max(int n)
{
	int ma=0;
	while(n>0)
	{
		int res = n%10;
		if(res>=ma)
		{
			ma=res;
		}
		n=n/10;
	}
	return ma;
}
int main ()
{
	int ans = 1;
	int n;
	cin>>n;
	if(n<=9)
		cout<<1;
	else if(n==10)
		cout<<2;
	else
	{
		while(n>10)
		{
		   n=n-max(n);
			ans++;
		}
		if(n==10)
			cout<<ans+1;
		else if(n<10)
			cout<<ans;
	}

	
	return 0;
}


第二次天梯赛
比赛时间为3小时,oi赛制。
题一:奶茶袋搜集
题解:贪心,以前没有怎么见过,结合了一点的差分数组和前缀和的思想,将每相邻两个数的差值从小到大排序,我们去掉最大的 m-1个差值,类比于在最大的m-1个差值
的地方分段,因为一个段中的极差等于两两相邻数的差之和,所以最后我们只要把最小的m-n个差值
相加即可。

题目如下:

代码如下:

点击查看代码
#include <bits/stdc++.h>
using namespace std;
int a[200010];
int s[200010];
int main(){
	int n,m;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) s[i]=s[i-1]^a[i];
	cin>>m;
	while(m--){
		int l,r;cin>>l>>r;
		cout<<(s[r]^s[l-1])<<endl;
	}
}

题目:该加训了
题解:首先要掌握一些离散数学的知识和位运算的知识,明白位运算结果可以化简成a^b,然后用前缀和的思想把数组的异或和求出来,不然会卡TLE,然后查询前l,到r的异或和。
题目如下:

输入输出


代码如下

点击查看代码
#include <bits/stdc++.h>
using namespace std;
int a[200010];
int s[200010];
int main(){
	int n,m;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) s[i]=s[i-1]^a[i];
	cin>>m;
	while(m--){
		int l,r;cin>>l>>r;
		cout<<(s[r]^s[l-1])<<endl;
	}
}
posted @ 2024-03-10 15:10  冬天的睡袋  阅读(53)  评论(0)    收藏  举报