牛客周赛 Round 98 [A-F]
小红很喜欢奇数。现在小红得到了一个正整数 x。小芳能帮他进行恰好一次如下操作:
操作:使得 x 加上自己的一个因子。
小红想知道小芳能不能帮他把 x 变成奇数,请你帮帮他。
//因为数据量不大,可以直接暴力。
void solve() {
int n;
cin >> n;
int ans = n;
for(int i = 1; i <= n; i++){
if(n % i == 0 && (ans + i) % 2 != 0){
cout << "Yes" << endl;
return;
}
}
cout << "No" << endl;
}
//当然仔细想一想,它是要相加得到奇数,那么可以知道 偶数 + 1(1一定是一个因子)= 奇数
void solve() {
cin >> n;
if (n % 2 != 0)
cout << "No" << endl;
else
cout << "Yes" << endl;
}
小红很喜欢 gcd 和 三角形。现在小红得到了两个正整数 x 和 y,请你帮她判断以 x、y 和 gcd(x, y) 这三个整数作为边长,能否组成一个非退化的三角形。
//莫得好说的
void solve() {
int x,y;
cin >> x >> y;
int ans = __gcd(x,y);
if(x + y > ans && x + ans > y && y + ans > x){
cout << "Yes" << endl;
}else{
cout << "No" << endl;
}
}
小红很喜欢 red。
现在小红拿到了一个长度为 n 的仅由 'r'、'e'、'd' 组成的字符串。小芳可以帮她进行任意次如下操作:
- 操作:将字符串的任意一位修改为
'r'、'e'、'd'中的一个字符。
小红不希望字符串中存在任何相邻且相同的字符,请你用尽可能少的操作次数修改字符串使其符合要求。
//看题意,就知道肯定得相邻的不同,而且才变化三个字母,可以直接扫过去
void solve() {
int n;
cin >> n;
string s;
cin >> s;
vector<char> chars = {'r', 'e', 'd'};
for (int i = 1; i < s.size(); i++) {
if (s[i] == s[i-1]) {
for (char c : chars) {
if (c != s[i-1] && (i+1 >= s.size() || c != s[i+1])) {
s[i] = c;
break;
}
}
}
}
cout << s <<endl;
}
题目描述
小红很喜欢 好数组。
定义一个数组是「好数组」当且仅当满足以下条件:
- 相邻元素不同(即数组中任意两个相邻的数不相等);
- 所有元素均为正整数。
现在输入一个正整数 n,你需要找到所有满足以下条件的数组:
- 数组的所有元素之和等于 n;
- 数组是「好数组」。
并按 字典序从小到大 的顺序依次输出所有满足条件的数组。
set<vector<int>> ans_set;
//第一感觉,肯定是用dfs去构造 sum = n的数组,然后全排列,判断能不能符合条件
void dfs(int target, vector<int> path, int start) {
//cout << target << " ";
if (target == 0) {
//cout << endl;
vector<int> ans_vec = path;
sort(ans_vec.begin(), ans_vec.end());
do {
bool flag = true;
for (int i = 0; i < ans_vec.size() - 1; i++) {
if (ans_vec[i] == ans_vec[i + 1]) {
flag = false;
break;
}
}
if (flag) {
ans_set.insert(ans_vec);
}
} while (next_permutation(ans_vec.begin(), ans_vec.end()));
return;
}
for (int i = start; i <= target; i++) {
path.push_back(i);
dfs(target - i, path, i);
path.pop_back();
}
}
void solve() {
int n;
cin >> n;
vector<int> path;
dfs(n, path, 1);
for (auto arr : ans_set) {
for (int num : arr) {
cout << num << " ";
}
cout << endl;
}
}
//后面想了一下,发现不需要去全排列
vector<int> ans_set;
void dfs(int sum, int n) {
if(sum == n){
for(auto num : ans_set){
cout << num << " ";
}
cout << endl;
return;
}
for (int i = 1; i <= n; i++) {
if(sum + i <= n && (ans_set.empty() || ans_set.back() != i)){
ans_set.push_back(i);
dfs(sum + i, n);
ans_set.pop_back();
}
}
}
void solve() {
int n;
cin >> n;
dfs(0,n);
}
小红很喜欢 gcd 和 sum。
小红定义一个长度为 k 的数组 {a₁, a₂, ..., aₖ} 的权值为:
权值 = gcd(a₁, a₂, ..., aₖ) × (a₁ + a₂ + ... + aₖ)
其中:
gcd(a₁, a₂, ..., aₖ)表示这些数的最大公约数(a₁ + a₂ + ... + aₖ)表示这些数的和
现在给定一个长度为 n 的数组 {a₁, a₂, ..., aₙ},小红可以从中选择一个非空子序列。请找到所有可能的非空子序列中权值最大的那个,并输出这个最大权值。
//一个想法是,我们把所有数字的因数都保存下来
//比如1或者2,是 2 6 4 的因数
//比如3,是 6 的因数
//比如4,是 4 的因数
//....
void solve() {
int n;
cin >> n;
vector<int> arr(n);
for(int i = 0; i < n; i++){
cin >> arr[i];
}
unordered_map<int, vector<int>> unorderedMap;
set<int> uniqueSet;
for(auto num : arr){
vector<int> tempVec;
//cout << "num = " << num <<endl;
for(int i = 1; i * i <= num; i++){
if(num % i == 0){
tempVec.push_back(i);
uniqueSet.insert(i);
if(num / i != i){
tempVec.push_back(num / i);
uniqueSet.insert(num / i);
}
}
}
for(auto d : tempVec){
//cout << d << " ";
unorderedMap[d].push_back(num);
}
//cout << endl;
}
// for(auto d : unorderedMap){
// cout << d.first << endl;
// for(auto c : d.second){
// cout << c << "->";
// }
// cout << endl;
// }
LL result = 0;
//然后我们枚举这些因数,得到哪些数字是共同存在这个因数的,把他们按照公式算一下求最大值
for(auto it = uniqueSet.rbegin(); it != uniqueSet.rend(); it++){
int d = *it;
auto nums = unorderedMap[d];
if(nums.empty()) continue;
int cur = nums[0];
LL sum = 0;
for(auto num : nums){
cur = __gcd(cur, num);
sum += num;
}
if(cur == d){
result = max(result, d * sum);
}
}
cout << result << endl;
}
// 实际上没那么复杂,要想得到最大值,肯定得是 2 4 6 8 或者是 12 24 36 这种拥有倍数关系的数字,很容易看出来最大公约数是2和12
// 如果不是倍数,极大可能最大公约数是1这种
oid solve()
{
int n;
std::cin >> n;
std::vector<int> cnt(N);
for (int i = 1; i <= n; i++) {
int x;
std::cin >> x;
cnt[x]++;
}
i64 ans = -1;
for (i64 i = 1; i < N; i++) {
i64 s = 0;
for (i64 j = i; j < N; j += i) {
s += j * cnt[j]; // ,后面算求和
}
ans = std::max(ans, i * s);//i为最大公约数
}
std::cout << ans << "\n";
}
小红很喜欢天使猫猫酱。
今天天使猫猫酱的题目过于简单,小红觉得不够过瘾,于是想出了一个更难的版本:
问题定义
有两个无限长的整数数组 a 和 b:
-
数组 a 的定义如下:
- 第 i 项 aᵢ = 22^m,其中 m 是由 i 个数字 '2' 连续拼接而成的十进制数。
- 举例:
- a₁ = 22^2
- a₂ = 22^22
- a₃ = 22^222
- ...(依此类推)
-
数组 b 的定义:
- 第 i 项 bᵢ = aᵢ 的正因子个数(包括 1 和 aᵢ 本身)。
问题要求
给定一个正整数 n,求数组 b 的前 n 项之和:
由于结果可能非常大,输出 S mod 998244353。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 998244353;
ll power(ll base, ll exp) {
ll res = 1;
base %= MOD;
while (exp > 0) {
if (exp & 1) res = res * base % MOD;
base = base * base % MOD;
exp >>= 1;
}
return res;
}
ll modinv(ll x) {
return power(x, MOD - 2);
}
ll sum(ll r, ll n) {
if (r == 1) return n % MOD;
ll numerator = (power(r, n + 1) - r + MOD) % MOD;
ll denominator = modinv(r - 1);
return numerator * denominator % MOD;
}
//这个数学推算比较复杂,建议直接看结论
//或者分段,先去就22^2....2的因数个数公式,然后再得到求和公式,最后简化
int main() {
ll n;
cin >> n;
cout << ((4 * sum(100, n) + 28 * sum(10, n) + 49 * (n % MOD)) % MOD * modinv(81) % MOD) << endl;
return 0;
}

浙公网安备 33010602011771号