第二次周赛题解

地址 http://acmteam.heyuantao.cn/contest.php?cid=1012
A 组成三位数
枚举第一个数,第二个数第三个数根据关系算出来,然后判断是否合法就行了。

#include<bits/stdc++.h> 
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
int vis[10] = {0};
bool fun(int n) {
	while(n) {
		int c = n % 10;
		if(vis[c]) return false;
		vis[c] = 1;
		n /= 10;
	}
	return true;
}
bool check(int a, int b, int c) {
	memset(vis, 0, sizeof vis);
	return fun(a) && fun(b) && fun(c);
}
int main() {
	rep(i, 123, 987) {
		int b = i * 2;
		int c = i * 3;
		if(check(i, b, c)) {
			printf("%d %d %d\n", i, b, c);
		}
	}
	return 0;
}

这是牛思琦的全排列做法

// http://acmteam.heyuantao.cn/problem.php?id=4104

/*签到题,没什么好说的。
不过第一次看到这道题的时候确实挺开心的,
因为以前了解了next_permutation和prev_permutation函数后
一直没机会用,哈哈哈哈 
*/ 

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int a[9]={1,2,3,4,5,6,7,8,9},cnt;
int main()
{
	do
	{
		int t1=a[0]*100+a[1]*10+a[2];
		int t2=a[3]*100+a[4]*10+a[5];
		int t3=a[6]*100+a[7]*10+a[8];
		if(2*t1==t2&&3*t1==t3)
			cout<<t1<<" "<<t2<<" "<<t3<<endl;
	}while(next_permutation(a,a+9));
	return 0;
} 

B New Year Candles
这就是个数学题,每b根用过的能合成一根新的,模拟一下就可以了。

#include<bits/stdc++.h>
using namespace std;
int main() {
	int a,b;
	scanf("%d%d", &a, &b);
	int f = 0, cnt = a;
	while(a >= b) {
		f = a % b;
		cnt += a / b;
		a = a / b + f;
	}
	cout << cnt;
	return 0;
}

**C 均分纸牌 **

这题我不会,诺姐原话:这题不是看一眼就出来了???膜拜大佬

题目中求的是最快多少次,那么你完全可以假定为最好情况,既每个大于平均数的数左边比他小的数刚好和大于平均数部分相等。因为如果大于平均数部分比左边欠的少的话,可以先通过右边更多的给他一部分。所以每个数最多只会加一次。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
int main() {
	int n, a[105] = {0}, sum = 0;
	scanf("%d", &n);
	rep(i, 1, n) {
		scanf("%d", &a[i]);
		sum += a[i];
	}
	sum /= n;
	int tot = 0, cnt = 0;
	rep(i, 1, n-1) {
		tot = a[i] - sum;
		if(tot) {
			a[i + 1] += tot;
			cnt++;
		}
	}
	cout << cnt;
	return 0;
}

**D 质因数分解 **

注意判断质数时候到 i * i 就可以了,否则会超时。

#include<bits/stdc++.h> 
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
bool isprime(int n) {
	if(n & 2 == 0  && n != 2) {
		return 0;
	}
	for(int i = 3; i * i <= n; i +=2) {
		if(n % i == 0)
			return 0;
	} 
	return n>1;
}
int main() {
	int n;
	scanf("%d", &n);
	rep(i, 2, sqrt(n)) {
		if(n % i == 0)
			if(isprime(i) && isprime(n / i)) {
				cout << n / i << endl;
				break;
			}
	}
	return 0;
}

第二种方法,不是通解。
首先,题目中告诉我们了n是两个质数的乘积。而我们知道两个质数的最大公约数是1,即n只有这两个质数为因子(1除外),那么我们可以直接一遍遍历遇到能整除的就是答案了。

#include<bits/stdc++.h>
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
int main() {
	int n;
	scanf("%d", &n);
	for(int i = 2; i * i <= n; ++i) {
		if(n % i == 0) {
			printf("%d", n / i);
			break;
		}
	}
	return 0;
} 

**E Jury Size **

如果你看懂题目了的话,这就是一个贪心。用map,可能因为有上一年的会是负数。
当然用数组也可以,只不过你要初始化的时候先加一个比ti大的数字。题目中100及以上都可以。

#include<bits/stdc++.h> 
using namespace std;
int date[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int fun(int m){
	int res = 0;
	for(int i = 1; i <= m; ++i) {
		res += date[i];
	}
	return res;
}
int main(){
	int n, res = 0;
	cin >> n;
	map<int, int> mp;
	for(int i = 0; i < n; ++i ) {
		int m, d, p, t;
		cin >> m >> d >> p >> t;
		int s = fun(m - 1) + d;
		for(int j = s - t; j < s; ++j) {
			mp[j] += p;
			res = max(res, mp[j]);
		}
	}
	cout << res << endl;
	return 0;
}

**F Regular Bracket Sequence **
判断有多少个合法括号序列,那么首先一种思路就是用栈模拟一下。

#include<bits/stdc++.h>
using namespace std;
int main() {
	string s;
	cin >> s;
	stack<int> st;
	int ans=0;
	for(int i=0; i<s.size(); ++i) {
		if(s[i]=='(')
			st.emplace(i);
		else{
			if(!st.empty()){
				ans+=2;
				st.pop();
			}
		}
	}
	cout << ans;
	return 0;
}

还可以对空间进行优化,因为只有左右括号,所以我们可以用一个变量记录某种括号数量。O(1)空间复杂度

#include<bits/stdc++.h>
#define rep(i, a, b) for(int i = a; i <= b; ++i)
using namespace std;
const int maxn = 1e6;
char s[maxn];
int main() {
	scanf("%s", s);
	int ans = 0, cnt = 0;
	for(int i = 0; i < strlen(s); ++i) {
		if(s[i] == '(') ++cnt;
		else if(cnt > 0) {
			--cnt;
			ans += 2;
		}
	}
	printf("%d", ans);
	return 0;
} 

**G 合并果子 **
首先一个思路就是每次选最小的两个合并,那么整体肯定是最优的。
如果用两重for时间复杂度很高。用优先队列可以优化到O(nlogn)。
和这题 修理牧场 思路完全一样

#include<bits/stdc++.h>
#include<cmath>
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
int main() {
	int n;
	scanf("%d", &n);
	priority_queue<int, vector<int>, greater<int>> q;
	rep(i, 1, n) {
		int x;
		scanf("%d", &x);
		q.push(x);
	}
	int sum = 0;
	while(q.size() != 1) {
		int a = q.top(); q.pop();
		int b = q.top(); q.pop();
		sum += a + b;
		q.push(a + b);
	}
	printf("%d", sum);
	return 0;
}
发布了33 篇原创文章 · 获赞 26 · 访问量 6335

猜你喜欢

转载自blog.csdn.net/qq_41829380/article/details/105676286