最近应老师的要求开始完成前几届的NOIP练习
这是2002年的题目
均分纸牌
题解
一道简单的贪心
直接求出最后要达到的平均数,并记录每一摞纸牌与平均数之间的差值,最后贪心+模拟求值
代码
#include <iostream>
#include <cstdio>
using namespace std;
int n, a[200];
long long sum = 0, ans;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), sum += a[i];
sum /= n;
for (int i = 1; i <= n; ++i) a[i] -= sum;
int i = 1, j = n;
while (a[i] == 0 && i < n) i++;
while (a[j] == 0 && j > 1) j--;
while (i < j) {
a[i + 1] += a[i];
a[i] = 0;
ans++;
i++;
while (a[i] == 0 && i < j) i++;
}
printf("%lld\n", ans);
return 0;
}
总结
直接一遍AC,没有什么低级的错误,本来也是一道《一本通》上分析过的题目,挺简单的,自行领悟
级数求和
题解
直接一个循环暴力+模拟
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int k, i;
double ans;
int main() {
scanf("%d", &k);
i = 1;
while (1) {
ans += 1.0 / i;
if (ans > k) break;
i++;
}
printf("%d\n", i);
return 0;
}
总结
暴力枚,直接A
选数
题解
搜索找每一种搭配方式,最后判断是否满足素数及选数的个数
但需要注意,先判断个数是否等于k,再判是否素数,可以省时
代码
#include <cstdio>
#include <iostream>
#define L 30
using namespace std;
int n, k, a[L], sum;
inline bool check(int x) {
if (x == 1) return 0;
for (int i = 2; i * i <= x; ++i)
if (x % i == 0) return 0;
return 1;
}
inline void dfs(int ans, int now, int cnt) {
if (cnt == k)
if (check(ans))
{ sum++; return ;}
for (int i = now; i <= n; ++i) {
dfs(ans + a[i], i + 1, cnt + 1);
}
}
int main() {
scanf("%d %d", &n, &k);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
dfs(0, 1, 0);
printf("%d\n", sum);
return 0;
}
总结
累计答案时先考虑的是否素数,以至于在codevs上T了一次