西北大学第四届程序设计竞赛新生赛

题目链接:https://ac.nowcoder.com/acm/contest/317
题解链接:https://www.cnblogs.com/nervendnig/p/10159666.html

A - 1e9个兵临城下

利用到了容斥原理,注意数据需要开成long long

#include <cstdio>
#include <iostream>
using namespace std;
const int n = 1e9;
typedef long long ll;

int main(void)
{
	ll t, a1, a2, a3, a12, a13, a23, a123;
	ll a, b, c, ans;
	scanf("%lld", &t);
	while (t--){
		scanf("%lld%lld%lld", &a, &b, &c);
		a1 = n / a;
		a2 = n / b;
		a3 = n / c;
		a12 = n / (a * b);
		a13 = n / (a * c);
		a23 = n / (b * c);
		a123 = n / (a * b * c);
		ans = a1 + a2 + a3 - a12 - a13 - a23 + a123;
		printf("%lld\n", n - ans);
	}
	
	return 0;
}

B - 抢课啦!

结构体排序

#include <iostream>
#include <algorithm>
using namespace std;

typedef struct{
	int id, cnt;
}cla;
cla arr[10005];

bool cmp(cla a, cla b)
{
	if (a.cnt != b.cnt)
		return a.cnt < b.cnt;
	else
		return a.id < b.id;
}

int main(void)
{
	int n, m, k, t;
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
		arr[i].id = i;
	for (int i = 1; i <= n; i++){
		cin >> k;
		while (k--){
			cin >> t;
			arr[t].cnt++;
		}
	}
	sort(arr + 1, arr + m + 1, cmp);
	for (int i = 1; i <= m; i++){
		cout << arr[i].id << ' ' << arr[i].cnt << endl;
	}
	return 0;
}

C - ICPC-无限路之城

完全图的边数

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;

int main(void)
{
	ll t, n, m;
	cin >> t;
	while (t--){
		cin >> n >> m;
		cout << n * (n - 1) / 2 - m << endl;
	}
	return 0;
}

D - 赌神

#include <iostream>
#include <algorithm>
using namespace std;

int main(void)
{
	int n, ans;
	while (cin >> n){
		ans = 0;
		while (n != 1){
			if (n % 2 == 1)
				n -= 1;
			else
				n /= 2;
			ans++;
		}
		cout << ans << endl;
	}
	return 0;
}

G - 卖萌型选手

这道题二分的话本人没写成
需要预先估计一下第多少项可爱度才能大于1e18
先在数组中保存好每一次的可爱度,再用upper_bound函数即可

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 5e6 + 5;

ll arr[N];

int main(void)
{
	ll t, k, idx;
	for (ll i = 1; i <= N - 5; i++)
		arr[i] = arr[i - 1] + i * i;
	scanf("%lld", &t);
	while (t--){
		scanf("%lld", &k);
		idx = upper_bound(arr, arr + N - 5, k) - arr - 1;
		printf("%lld\n", arr[idx]);
	}
	return 0;
}

I - 曾有你的森林,あなたがいた森

这道题用到了尺取法

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5 + 5;
const int INF = 0x3f3f3f3f;

bool flag[N];
int arr[N];
int num[N], cnt;

int main(void)
{
	int t, n, m, k;
	int l, r, ans;
	scanf("%d", &t);
	while (t--){
		scanf("%d%d%d", &n, &m, &k);
		for (int i = 1; i <= n; i++)
			scanf("%d", &arr[i]);
		
		cnt = 0;
		ans = INF;
		memset(flag, 0, sizeof flag);
		memset(num, 0, sizeof num);
		l = 1, r = 1;
		
		while (true){
			while (r <= n && cnt < k){
				if (arr[r] <= k && flag[arr[r]] == 0)
					cnt++;
				num[arr[r]]++;
				flag[arr[r]] = 1;
				r++;
			}
			if (cnt < k)
				break;
			ans = min(r - l, ans);
			
			if (num[arr[l]] == 1 && arr[l] <= k){
				cnt--;
				flag[arr[l]] = 0;
			}
			num[arr[l]]--;
			l++;
		}
		if (ans == INF)
			printf("-1\n");
		else
			printf("%d\n", ans);
	}
	return 0;
}

L - 鸡尾酒买罐子

因为这道题是是只要钱大于当前罐子就会买下,如果前面有一个很贵的罐子,后面全是便宜的罐子,这样会买下贵的罐子,所以不是钱越多越好。不具有单调性,所以不能二分
从1枚举到min(sum + 1, n),一开始写成了min(sum, n)错了一次
因为罐子的价格可能会为0,所以sum+1也要枚举

#include <iostream>
#include <algorithm>
using namespace std;

int a[305], sum;

int main(void)
{
	int n, m, k;
	int money, cnt;
	cin >> n >> m >> k;
	for (int i = 1; i <= k; i++){
		cin >> a[i];
		sum += a[i];
	}
	for (int i = 1; i <= min(sum + 1, n); i++){
		money = i;
		cnt = 0;
		for (int j = 1; j <= k && money; j++){
			if (money >= a[j]){
				money -= a[j];
				cnt++;
			}
		}
		if (cnt >= m){
			cout << i << endl;
			return 0;
		}
	}
	cout << "poor chicken tail wine!" << endl;
	return 0;
}
发布了199 篇原创文章 · 获赞 26 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_43772166/article/details/104117904
今日推荐