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”的。

数据范围

思路

二进制问题常见思考角度

将每个数拆分成二进制,记录每一位出现过多少次

  1. 若该位出现过两次,则必然存在两个数异或后的平方更小
  2. 若最高位出现过一次,但是对于其他数也出现过一次,同样使得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 $ 是一个置换,可分解为若干个环)。

需完成两步操作:

  1. 2个居民 禁止结婚;
  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;
} 
posted @ 2025-09-05 12:21  归游  阅读(4)  评论(0)    收藏  举报