2025牛客暑期多校训练营2
Identical Somehow
题目大意
给定整数 x 与 y(a≠y),判断是否存在正整数 k,使得
H(x)=H(y)
其中 H(x)= x mod k + k mod x。
若存在,输出任意一个 k;否则输出 -1。
数据范围
多组数据,数据组数 T≤10⁴,1≤a,y≤10⁹。
思路
易得k=1的时候满足,但是注意x,y不能一个为1,一个不为1
点击查看代码
//2025牛客暑期多校训练营2
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve() {
ll x, y;
cin >> x >> y;
if (x == 1 && y != 1 || x != 1 && y == 1) {
cout << -1 << "\n";
} else {
cout << 1 << "\n";
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int _ = 1;
cin >> _;
while (_--) {
solve();
}
return 0;
}
Bitwise Perfect
题目大意
有 $ T $ 组蚂蚁群,每组有 $ n $ 只蚂蚁,初始力量为 $ a_1, a_2, \dots, a_n $。战争中会恰好一次随机选一对不同的蚂蚁 $ (i,j) ( i<j )$,让它们消失并生成一只力量为 $ a_i \oplus a_j $(异或)的新蚂蚁。
蚁群的“总力量”定义为所有蚂蚁力量的平方和 $ \sum_{k=1}^n a_k^2 $。若对于任意选法 $ (i,j) $,替换后的总力量都不小于原来的总力量,则称该蚁群是“bitwise perfect”的。
数据范围
思路
二进制问题常见思考角度
将每个数拆分成二进制,记录每一位出现过多少次
- 若该位出现过两次,则必然存在两个数异或后的平方更小
- 若最高位出现过一次,但是对于其他数也出现过一次,同样使得bit perfect 不存在
点击查看代码
//2025牛客暑期多校训练营2
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve() {
ll n;
cin >> n;
vector<ll> a(n), b(64, 0), c(64, 0);
for (ll i = 0; i < n; i++) {
cin >> a[i];
for (ll j = 63; j >= 0; j--) {
if (a[i] & (1ll << j)) {
b[j]++;
break;
}
}
for (ll j = 63; j >= 0; j--) {
if (a[i] & (1ll << j)) {
c[j]++;
}
}
}
for (ll i = 0; i < 64; i++) {
if (b[i] > 1 || b[i] == 1 && c[i] > 1) {
cout << "NO\n";
return;
}
}
cout << "YES\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int _ = 1;
cin >> _;
while (_--) {
solve();
}
return 0;
}
Another Day of Sun
题目大意、
有一个长度为 $ n $ 的数组,部分位置是确定的 $ 0 $ 或 $ 1 $,还有 $ k $ 个位置是模糊的(每个模糊位置可视为 $ 0 $ 或 $ 1 $),因此总共有 $ 2^k $ 种可能的数组。
对于每一种可能的数组,你需要计算:与该数组所代表的记录一致的、肖恩至少看到一次阳光的最少天数。将所有不同数组的结果相加,最终结果是多少?。
注意连续的1视为同一天有太阳
数组可能是 [1,1,1] 或者 [1,0,1]。若数组为 [1,1,1],这些记录可以在同一天记录,因此肖恩可能是在同一天见到了阳光,结果为 1;若数组为 [1,0,1],第一条和第三条记录必须是在不同天数记录的,因此肖恩至少见到了 2 天的阳光。所以答案是 1 + 2 = 3
数据范围
- 测试用例数 $ T : 1 \leq T \leq 10^4 $;
- 每组笔记数量 $ n : 2 \leq n \leq 5 \times 10^5 $,且所有测试用例的 $ n $ 总和 $ \sum n \leq 5 \times 10^5 $;
- 单条笔记的数值 $ a_i $:仅能取 \(-1\)(表示未知)、$ 0 $ 或 $ 1 $。
思路
dp经典题
需要设置多个状态进行相互转移到最终态
f[i][0]:前 i 天中,第 i 天为 0 时,所有可能序列的 “最少阳光天数” 总和(每个序列的贡献是其包含的 1 的块数)。
f[i][1]:前 i 天中,第 i 天为 1 时,所有可能序列的 “最少阳光天数” 总和。
g[i][0]:前 i 天中,第 i 天为 0 时,所有可能的序列总数(辅助计算,用于统计 “前 i 天为 0” 的序列数量)。
g[i][1]:前 i 天中,第 i 天为 1 时,所有可能的序列总数
对于a[i]不是0
f[i][1]=(0ll+f[i-1][1]+f[i-1][0]+g[i-1][0])
第i个为1,所以最少阳光天数直接等于f[i-1][1],这样保持最少,同时加上第i-1个为0的序列的最少阳光天数,还要加上所有i-1为0的序列的数量,因为这些序列会因为第i个为1对f[i][1]作出贡献
g[i][1]=(0ll+g[i-1][0]+g[i-1][1])
更新第i天为1的序列数量
以下的转移可做思考
对于a[i]不是1
f[i][0]=(0ll+f[i-1][1]+f[i-1][0])
g[i][0]=(0ll+g[i-1][1]+g[i-1][0])
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+10;
const int mod=998244353;
int a[maxn];
int f[maxn][3],g[maxn][3];
//f[i][0/1]:前 i 天的序列中,第 i 天为 0/1 时,所有可能序列的最少阳光天数之和。
//g[i][0/1]:前 i 天的序列中,第 i 天为 0/1 时,满足条件的序列数量(用于辅助计算)
void solve(){
int n;
cin>>n;
for(int i=1;i<=n;++i) cin>>a[i];
for(int i=1;i<=n;++i)
f[i][0]=f[i][1]=g[i][0]=g[i][1]=0;
if(a[1]!=0)
f[1][1]=g[1][1]=1;
if(a[1]!=1)
f[1][0]=0,g[1][0]=1;
for(int i=2;i<=n;++i){
if(a[i]!=0){
f[i][1]=(0ll+f[i-1][1]+f[i-1][0]+g[i-1][0])%mod;
g[i][1]=(0ll+g[i-1][0]+g[i-1][1])%mod;
}
if(a[i]!=1){
f[i][0]=(0ll+f[i-1][1]+f[i-1][0])%mod;
g[i][0]=(0ll+g[i-1][1]+g[i-1][0])%mod;
}
}
cout<<(f[n][0]+f[n][1])%mod<<endl;
return ;
}
int main(){
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}
Love Wins All
题目大意
社区有 $ n $ 个居民($ n $ 是偶数),每个居民 $ i $ 有唯一的心上人 $ a_i $(即 $ a $ 是一个置换,可分解为若干个环)。
需完成两步操作:
- 选 2个居民 禁止结婚;
- 剩下的 $ n-2 $ 个居民组成 $ \frac{n}{2} - 1 $ 对夫妻,且每对夫妻必须满足“$ x $ 爱 $ y $ 或 $ y $ 爱 $ x $”。
求满足条件的不同婚姻计划的总数,结果对 $ 998244353 $ 取模。
(注:婚姻计划不同的判定:存在居民已婚状态不同,或存在两人的夫妻关系不同。)
数据范围
多组测试用例,每组输入:
- 第一行:偶数 $ n $(居民数量,满足 $ 4 \leq n \leq 5 \times 10^5 $);
- 第二行:$ n $ 个整数组成的排列 a ( \(a_i\) 表示居民 $ i $ 所爱的人)。
测试用例总数 $ T \leq 10^4 $,所有测试用例的 $ n $ 之和不超过 $ 5 \times 10^5 $。
思路
容易发现,对于心上人的关系,可以形成环
如果形成奇环,在配对后总会有个单身狗,所以,必须删除奇数环
而当奇数环为1个或者>2个的时候,删除后仍然不能达成全部配对
而当奇数环为2个时,必须删除这两个环各一个数,达成偶数环,此时的每个环最多有2种配对方式,环只有两个人时只有一种,按照乘法原理计算总方案
而全都是偶数环时,两个人只有一种方式,此时需要删除同一个环中的两个珠子,>2的环有i*i/4种(i为环的大小),将环看成黑白珠交替,选黑珠时,只能选择白珠,因此黑珠有i/2个,每个可选i/2个白珠
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
#pragma GCC optimize("O3")
using ll=long long;
#define x first
#define y second
#define endl "\n"
using pii=pair<int,int>;
const int maxn=5e5+10;
const int mod=998244353;
inline ll read()
{
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9')
x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void print(ll x)
{
if(x<0)
putchar('-'),x=-x;
if(x>9)
print(x/10);
putchar(x%10+'0');
return;
}
ll qpow(ll a,ll b){
ll res=1;
a%=mod;
while(b){
if(b&1) res=res*a%mod;
b>>=1;
a=(a*a)%mod;
}
return res%mod;
}
void solve(){
ll n=read();vector<ll> f(n+1);
for(int i=1;i<=n;++i) f[i]=read();
vector<ll> c;
vector<bool> book(n+1,0);
for(int i=1;i<=n;++i){
if(!book[i]){
ll cnt=0;
ll now=i;
while(!book[now]){
book[now]=1;
now=f[now];
++cnt;
}
c.push_back(cnt);
}
}
ll x=0;
for(auto i:c) x+=i%2;
if(x>2 || x==1) {
print(0ll);
puts("");
return ;
}
else if(x==2){
ll ans=1;
for(auto i:c){
if(i%2)
ans=ans*i%mod;
else if(i!=2)
ans=ans*2%mod;
}
print(ans);
puts("");
return ;
}
for (auto i:c) if (i > 2) x++;
ll y = qpow(2, max(x - 1, 0ll)), ans = 0;//y是其他环组成的选择方案数
x = qpow(2, x);
for (auto i:c) {
if (i!= 2) {
ans = (ans + i*i/4*y% mod) % mod;
} else {
ans = (ans + i*i/4*x% mod) % mod;
}
}
print(ans);
puts("");
return ;
}
int main(){
ll _=1;
_=read();
while(_--){
solve();
}
return 0;
}

浙公网安备 33010602011771号