寒假题单-题解

寒假题解

Zy的白日梦

思路

商品的总金额计算完后再进行抹零。

可以使用数组存储所有数据,再判断;亦可直接输入判断,用变量 \(vip\) 表示是否为会员,如果是会员,则每件物品打对应的折扣。

输入时注意是小数输入,输出保留小数点后 \(3\) 位。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int N, p, vip;
double ans, x, y, sum;

int main(){
    cin >> N;
    while(N--) {
        cin >> p >> vip;

        sum = 0.0;
        for (int i = 0; i < p; ++i) {
            cin >> x >> y;
            if (vip) sum += x * y;
            else sum += x;
        }

        ans += (sum * 10 - int(sum * 10)) / 10;
    }

    cout << fixed << setprecision(3) << "$" << ans << endl;
    return 0;
}

Zy的宝藏

思路

考察数学,若模拟,只能拿到部分,观察前几项得到规律或者推导出来。

\(i\) 次,将所有 \(i\) 的倍数米切换状态。

所以,对于第 \(k\) 米状态,它切换的次数恰好是 \(k\) 的约数的个数。如果 \(k\) 有偶数个约数,那么最后第 \(k\) 米一定没有埋下宝箱。如果 \(k\) 有奇数个约数,则第 \(k\) 米一定埋下宝箱。

那么 \(k\),如果有约数 \(x\),则一定有约数 \(\frac{k}{x}\)。若 \(x^2 \neq k\),约数都是成对出现的。说明,只有当 \(k\) 是完全平方数时候,它会有奇数个约数,否则一定有偶数个约数。

因此找出 \(1,2,..N\) 中的完全平方数的个数即可,答案为 \(\lfloor \sqrt{n} \rfloor\)

代码

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

int N;

int main(){
    cin >> N;
    cout << (int)sqrt(N);
    return 0;
}

数字缩水

思路

注意数据大小 \(10^{1000}\)\(1000\) 位的整数,需要将整数作为字符串处理。

贪心算法,策略:每一次删除一位要使得随后得到的整数为最大,高位数字应该继续保持高位,因此寻找最小数字不可行。

例如:\(3241\),若寻找最小值 \(1\),得到 \(324\) 小于取 \(2\) 删除后的数字 \(341\)

因此最佳的策略:从左向右寻找第一个小于右侧数字,删除此数字一定为最大,若没有找到,那么删除最后一位保持所有高位(除个位以外)均最大。

代码

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

string s;

int main(){
    cin >> s;
    // 循环输出 m - 1 次删除后的整数
    for (int m = s.length(); m >= 1; --m) {
        bool isok = false;
        int deletes;
        // 寻找第一个小于右侧的数字,若存在直接删除这个位置上的数字,否则删除最后一位
        for (int j = 0; j < s.length() - 1; ++j) {
            if (s[j] < s[j + 1]) {
                deletes = j;
                isok = true;
                break;
            }
        }

        // 删除数字
        if (isok) s.erase(deletes, 1);
        else s.erase(s.length() - 1);

        cout << s << endl;
    }
    return 0;
}

【寒假-特别题目】最小字符串

思路

字符串sort排序即可,最后依次输出。

代码

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

string ss[505];

int main() {
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> ss[i];
	}
	sort(ss + 1, ss + n + 1);
	for (int i = 1; i <= n; i++) {
		cout << ss[i];
	}
	return 0;
}

【寒假-特别题目】是否有下一个身份

思路

下一个全排列可以使用 \(next\)_\(permutation()\) 函数获取,当然可以自行写出\(O(N)\)下一个全排列的代码。

代码

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

string s, r;

int main() {
	while (cin >> s) {
		if (s == "#") break;
		r = s;
		next_permutation(s.begin(), s.end());	// 下一个全排列,在原字符串基础上修改
		if (s > r) cout << s << nl;
		else cout << "BOSS" << nl;
	}
	return 0;
}

【寒假-特别题目】寻找中位数

思路

快速排序取需要找的区间继续划分或 \(nth\)_\(element()\) 函数求得第 \(k\) 个数字,会将该区间数据重新排列,前 \(k - 1\) 个数字均小于等于第 \(k\) 个数字,后面的所有数字均大于等于第 \(k\) 个数字。

代码

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

vector<long long> v;
int n;

int main() {
	cin >> n;
	while (n--) {
	    long long x;
	    cin >> x;
		v.push_back(x);
		long long ans = 0, midden = v.size() / 2;	// 中位数的位置

		nth_element(v.begin(), v.begin() + midden, v.end());
		ans += v[midden];
		// 若是偶数个,需要再加上一个中位数的和除以二
		if (v.size() % 2 == 0) {
			nth_element(v.begin(), v.begin() + midden - 1, v.end());
			ans = (ans + v[midden - 1]) / 2;
		}

		cout << ans << nl;
	}
	return 0;
}
posted @ 2023-01-23 19:41  guanglong  阅读(69)  评论(0)    收藏  举报