绍兴文理学院元培学院第十五届大学生程序设计竞赛

题目集入口 - 补题 (pintia.cn)

目录

1.爱的素数(分析题)

2.规划一(最小生成树)

3.物资转移(贪心)

4.前四位(高精度)

5.上流的聚餐(并查集)

6.庄生的笔(分析题)


1.爱的素数

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int vis(ll n) {
	int c = 1;
	for (int i = 2; i * i <= n; i++) {
		if (n % i == 0)
			c = 0;
	}
	if (n <= 1)
		return 0;
	if (c == 0)
		return 0;
	else
		return 1;
}

int su(ll l, ll r) {
	int sum = r - l + 1, k = 0;
	for (ll i = l; i <= r; i++) {
		if (vis(i))
			k++;
	}
	if (k * 1.0 / sum >= 0.5)
		return 1;
	else
		return 0;
}

int main() {
	ll l, r;
	while (cin >> l >> r) {
		if (r - l + 1 >= 20) {//素数很少,由推理可知达到所给区间超过一定范围,就不能构成爱的素数
      //不能是10的原因:可能所给区间是(2,12),其中有2,3,5,7,9,11共6个素数
			puts("no");
		} else {
			if (su(l, r))
				puts("yes");
			else
				puts("no");
		}
	}
	return 0;
}

错因:没有仔细分析题意,多思考一会,而是直接按照题意找素数,造成了超时;

反思:遇到容易超时(或数据范围给的很大的题目),先仔细分析题意,看看有没有其他的突破口(找规律,或者题目中某些关键字眼) 

2.规划⭐⭐⭐

#include <bits/stdc++.h>
using namespace std;
int n, m;
const int N = 1e5 + 100;
typedef long long ll;

struct lu {
	int u, v, w;
} k[N];
int f[N];

void chushihua() {
	for (int i = 0; i <= n; i++) {
		f[i] = i;
	}
}

ll find(ll x) {
	return x == f[x] ? x : f[x] = find(f[x]);
}

bool cmp(lu a, lu b) {
	return a.w < b.w ;
}

int main() {
	ll sum = 0,ans=0;
	cin >> n >> m;
	chushihua();
	for (int i = 1; i <= m; i++) {
		cin >> k[i].u >> k[i].v >> k[i].w;
	}
    sort(k + 1, k + m + 1, cmp);//排序,找费用最小的边相连
	for (int i = 1; i <= m; i++) {
		ll a = find(k[i].u);
		ll b = find(k[i].v);
		if(a!=b){
            ans++;
            f[a] = b;
		sum += k[i].w;
        }
    }
	if (ans < n-1)//由最小生成树的性质知:由n-1条边相连,所以若小于n-1条边,一定有没有联通的村庄
		puts("NO");
	else
		cout << sum << endl;
    return 0;
}

最小生成树笔记:(6条消息) 最小生成树详解(模板 + 例题)_潘小蓝的博客-CSDN博客_最小生成树例题详解

 3.物资转移

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;//开long long !!!
priority_queue<ll,vector<ll>,greater<ll> >q;
int main(){
  ll n;
  while(cin>>n){
  	ll sum=0;
  for(int i=0;i<n;i++){
  	ll a;
  	cin>>a;
  	q.push(a);
  } 
  while(!q.empty()){
  	ll len=q.size();
  	if(len<=1)break;
  	ll a=q.top();
  	q.pop();
  	ll b=q.top();
  	q.pop();
  	ll c=min(a,b);
  	sum+=c;
	  q.push(a+b);
  }
  while(!q.empty()){
  	ll m=q.top();
	  sum+=m; 
	  q.pop();
	  //k++;
  } 
  //cout<<k<<endl;
  cout<<sum<<endl;
}
	return 0;
} 

错因:没开long long (emmm........) 本来是做过类似的题,以为很容易就可以过,万万没想到还是卡在了long long,(即使是优先队列里的数据类型也逃不过long long)

总结:下次能开long long 的,坚决不写int了(还有,只要是实在找不到逻辑上的错误,过不了多半了long long)

4.前四位⭐⭐⭐

/*#include <bits/stdc++.h>
using namespace std;

int main() {
	int n;
	cin >> n;
	double ans = 1;
	for (int i = 0; i < n; i++) {
		ans *= n;
		while (ans >= 10000)
			ans /= 10;
	}
	cout << int(ans);
	return 0;
}*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
	int n;
	cin >> n;
	double res = n * log10(n) - (int)(n * log10(n));
	int ans = pow(10, res) * 1000;
	cout << ans << endl;
	return 0;
}

 

5.上流的聚餐⭐⭐⭐

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 100;
typedef long long ll;
int n;

struct node {
	ll a, b, c;
} m[N];
ll f[N];

void chushihua() {
	for (int i = 1; i <= n; i++)
		f[i] = i;
}

ll find(ll x) {
	return x == f[x] ? x : find(f[x]);
}

void lianxi(ll a, ll b) {//建立朋友间的联系
	ll x = find(a);
	ll y = find(b);
	if (x != y)
		f[x] = y;
}
vector<int>s[N];

int main() {
	ll ans = -0x7FFFFFFF;
	cin >> n;
	chushihua();
	for (int i = 1; i <= n; i++) {
		cin >> m[i].a >> m[i].b >> m[i].c;
		lianxi(i, m[i].a);
	}
	for (int i = 1; i <= n; i++) {
		s[find(i)].push_back(m[i].b);//将某个队伍所有的礼物都放到该队伍中最后一个被联系的人的包里
		s[find(i)].push_back(m[i].c);
	}
	for (auto i : s) {//遍历二维动态数组的第一维(遍历所有队伍)
		ll mi, ma;
		vector<int>v = i;//新建一个动态数组表示原二维数组的第二维(遍历每个队伍里的礼物)
		sort(v.begin(), v.end());
		ll cnt = 0;
		for (auto it : v) {
			cnt++;
			if (cnt == 1)
				mi = it;//该队伍里的礼物最小值
			if (cnt == v.size())
				ma = it;//该队伍里的礼物最大值
		}
		ans = max(ans, ma - mi);//找所有队伍里差值最大的那个
	}
	cout << ans << endl;
}

6.庄生的笔

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e3;
map<string, int>mp;

int main() {
	ll n, m, cnt = 0;
	cin >> n >> m;
	for (int i = 0; i < n; i++) {
		string x1, y1, x2, y2, s1, s2;
		cin >> x1 >> y1 >> x2 >> y2;
		s1 = x1 + y1, s2 = x2 + y2;
		mp[s1]++;
		mp[s2]++;
		if (mp[s1] > 1 || mp[s2] > 1)
			continue;
		else
			cnt++;
	}
	if (cnt <= m)
		puts("yes");
	else {
		puts("no");
		cout << cnt - m << endl;
	}
	return 0;
}

分析:比赛的时候被题面吓到了,还以为又是个图或是树的题,仔细分析发现某个点出现超过一次就一定有连边(即可以一笔画画完),这样只要把坐标存起来,cnt计数只出现一次的坐标 即可

反思:这次比赛出现了很多问题,比如很多改写出来的题目没能写出来,就连第一个简单的签到题也因为把两个样例输入看成输入和输出贰卡了进一个小时,再如素数和庄生的笔的题,仔细分析后也很容易,但是因为自己不仔细思考而错过。

总结:拿到一个题后不要着急先仔细从头到尾审一遍题,然后先考虑不用任何算法能否写出,最后再去考虑是什么算法,不要着急看时间,相信自己可以的,不要慌张,认真思考,还有记得开long long (是所有的变量!!!)


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值