牛客周赛 Round 108 CDEF题解

C、小苯的数字合并

题意:

小苯有一个长度为 $ n $ 的数组 $ a_1, a_2, \ldots, a_n $,他可以对 $ a $ 进行任意次“数字合并”操作,具体地,一次数字合并操作描述为:

  • 选择一个下标 $ i $ ($ 1 \leq i < |a| $),将 $ a_i $ 和 $ a_{i+1} $ 合并为一个数字,结果为两个的和 $ a_i + a_{i+1} $。合并后数组长度减 1,下标按新数组重新编号。

现在小苯可以进行任意次上述操作,他想知道他可以得到多少种本质不同结果数组,请你帮他数一数吧。换句话说,在可以进行任意次操作的情况下,所有可能得到的数组 $ a $ 有多少种本质不同的模样。由于答案可能很大,请将答案对 $ 998,244,353 $ 取模后输出。

思路:

对于任意的合并操作,数组一定改变。
数组长度:2 3 ... n
res: 2 4 ... \(2^{n - 1}\)
直接输出\(2 ^ {n - 1}\)即可

代码

 cout << pow_mod(2, n - 1) << '\n';

D、小苯的子序列权值

题意:

小苯有一个长度为 \(n\) 的序列 \(a_1, a_2, \ldots, a_n\),他认为一个序列的权值为:序列中所有数字的按位与。
现在小苯想知道所有的非空(显然一共 \(2^n - 1\) 个)的子序列\footnote{子序列是指从原序列中选取若干个元素(可以不连续)形成的序列} 中,有多少个子序列的权值是偶数,请你帮他算一算吧。由于答案可能很大,请将答案对 \(998\,244\,353\) 取模后输出。

思路:

考虑用所有子序列的情况减去子序列为奇数的情况
子序列为奇数的情况:序列中所有元素均为奇数,情况有:\(2^{cnt - 1}\)\({cnt为奇数的个数)\)

代码

  cout << (ksm (2, n) - ksm (2, numn) +2 * mod) % mod << "\n";

E、小苯的数字合并

题意:

小苯发现了一些「有趣的」数字,即:数字本身是个完全平方数,且其各个数位之和也是个完全平方数!例如 \(2025\) 本身就是个完全平方数,同时其各个数位之和:\(2 + 0 + 2 + 5 = 9\) 也是个完全平方数,因此小苯认为 \(2025\) 就是个「有趣的」数字。

现在小苯有一个长度为 \(n\) 的序列 \(a_1, a_2, \ldots, a_n\),他可以对 \(a\) 做任意次以下操作:
选择两个不同的下标 \(i, j\) (\(1 \leq i, j \leq n; i \neq j\)),满足 \(a_i \geq 2\),随后将 \(a_i\) 减去 \(1\)\(a_j\) 加上 \(1\)
他想知道,自己至多可以把 \(a\) 中多少个数字变成「有趣的」数字,请你帮他算一算吧

思路:

因为1也是有趣的数字,所以前n-1位均填1,则答案至少为n-1。现在考虑能否填满,即在符合条件的数字中选择n个是否能够刚好填满,考虑dp即可。
dp[i, j] 使用总和为i的数,能否填j个数字

代码

#include<bits/stdc++.h>
#define ll long long
#define ce cerr
#define ull unsigned long long
#define lll __int128
#define PII pair<int, int>
#define PLL pair<long ,long>

using namespace std;

const int inf = 0x3f3f3f3f;
const ll iinf = 1e18;

//cin.ignore(std::numeric_limits< streamsize >::max(), '\n');
int t;
vector<int> vec;
int n;
vector<vector<int> > dp (2e4 + 1, vector<int> (105, 0));
void init () {
	 vec.push_back (inf);
	 for (int i = 1; i <= 20000; ++i) {
	 	 int q = sqrt (i);
	 	 if (q * q == i) {
	 	 	int temp = i;
	 	 	int res = 0;
	 	 	while (temp) {
	 	 		 res += temp % 10;
	 	 		 temp /= 10;
	 	 	}
	 	 	q = sqrt (res);
	 	 	if (q * q == res) {
	 	 		 vec.push_back (i);
	 	 	}
	 	 }
	 }
	 int nn = vec.size ();
	      // dp : 使用总和为i的数,能否组成j个数字
     //for (auto i : vec) ce << i << " ";
     dp[0][0] = 1;
     for (int i = 1; i <= 2e4; ++i) {
     	 for (int j = 1; j <= 104; ++j) {
     	 	 for (int k = 1; k <= nn - 1 && i - vec[k] >= 0; ++k) {
     	 	 	 dp[i][j] = dp[i][j] | dp[i - vec[k]][j - 1];
     	 	 }
     	 }
     }
}
void solve() {
	 cin >> n;
	 int sum = 0;
     for (int i = 1; i <= n; ++i) {
     	 int x;
     	 cin >> x;
         sum += x;
     }
     if (dp[sum][n] == 1) {
     	 cout << n << "\n";
     }else{
     	 cout << n - 1 << "\n";
     }
}
int main() {
	 ios::sync_with_stdio (false);
	 cin.tie(NULL);
	 cout.tie(NULL);
	 t = 1;
	 cin >> t;
	 init ();
	 while (t --) {
	 	 solve();
	 }
	 return 0;
}
posted @ 2025-09-20 00:01  Li_Yujia  阅读(23)  评论(0)    收藏  举报