题解:P17129 [ICPC 2025 Shanghai R] Round screws
非常好的一道题。
设
经典结论
那你对一段操作其实也是同理的,会把前面所有的都变成
因此,我们可以设计
考虑优化这个转移,首先这个可以放到值域上去做,时间复杂度
我们设
AC Code
#include<bits/stdc++.h>
#define int long long
using namespace std ;
const int MAXN = 1e5 + 7 ;
const int INF = 1e18 + 7 ;
int a[MAXN] , b[MAXN] ;
int sum[MAXN] ;
int dp[MAXN] ;
int g[1 << 9][1 << 9] ;
void solve() {
int n , p ;
cin >> n >> p ;
int mx = 0 ;
for (int i = 1 ; i <= n ; i ++) {
cin >> a[i] ;
b[i] = a[i] ^ a[i - 1] ;
mx = max(mx , b[i]) ;
}
b[n + 1] = a[n] ;
for (int i = 1 ; i <= n + 1 ; i ++) {
sum[i] = sum[i - 1] ^ b[i] ;
dp[i] = INF ;
}
memset(g , 0x3f , sizeof(g)) ;
for (int i = 0 ; i < (1 << 9) ; i ++) {
g[0][i] = i ;
}
for (int i = 1 ; i <= n + 1 ; i ++) {
int t = (sum[i] & ((1 << 18) - (1 << 9))) ;
int l = sum[i] & ((1 << 9) - 1) ;
for (int j = 0 ; j < (1 << 9) ; j ++) {
dp[i] = min(dp[i] , g[j][l] + ((j << 9) ^ t) + p * (i - 1)) ;
}
for (int j = 0 ; j < (1 << 9) ; j ++) {
g[t >> 9][j] = min(g[t >> 9][j] , dp[i] + (l ^ j) - p * i) ;
}
}
// for (int j = 1 ; j <= n + 1 ; j ++) {
// for (int k = 0 ; k < j ; k ++) {
// dp[j] = min(dp[j] , dp[k] + p * (j - k - 1) + (sum[j] ^ sum[k])) ;
// }
// }
//
cout << dp[n + 1] << "\n" ;
}
signed main() {
// freopen("xor.in" , "r" , stdin) ;
// freopen("xor.out" , "w" , stdout) ;
ios::sync_with_stdio(0) ;
cin.tie(0) ;
cout.tie(0) ;
int t ;
cin >> t ;
while (t--) {
solve() ;
}
return 0 ;
}