1. 程式人生 > >[題解]Mail.Ru Cup 2018 Round 1 - D. Changing Array

[題解]Mail.Ru Cup 2018 Round 1 - D. Changing Array

【題目】

D. Changing Array

【描述】

給n個整數a[1],...,a[n],滿足0<=a[i]<=2^k-1。Vanya可以對這n個數中任一多個數進行操作,即將x變為x',其中x'指x限制在k位內二進位制取反。問a[1],...,a[n]中最多有多少個連續子段的異或和不為0。

資料範圍:1<=n<=200000,1<=k<=30

【思路】

為了敘述方便,記MAX=(1<<k)-1,即二進位制下k位全是1的數。

為了符號表示不產生歧義,以下使用^表示異或(上面的題目描述中指的是次方)。

這裡要用到異或運算的一個很重要的性質,即x^x=0。

根據定義,x^x'=MAX,從而x'=x^x^x'=x^MAX。

先不考慮a[1],...,a[n]的變化。維護字首異或和s[i],於是a[i]^...^a[j]=s[j]^s[i-1]。那麼,a[i]^...^a[j]==0當且僅當s[j]==s[i-1]。為了讓連續子段異或和為0儘量少,就是要讓s[i]儘量不同。

再看改變某個a[i]會帶來的影響。將某個a[i]變為a[i]^MAX,那麼包含a[i]的字首異或和s[j]都要變為s[j]^MAX,即s[j]變為s[j]^MAX對所有j>=i。這個時候發現,如果再改變a[i+1],則s[k]又都變回去了對所有k>=i+1。這說明可以通過改變某些a[i]實現將某一個s[j]變為s[j]^MAX。

這個時候有個很自然的想法就是,值為x和x^MAX的那些s[i]應該放在一類中考慮,因為它們最多隻有兩個值,要想使得“在其中挑兩個數,它們不相等”的概率最小,只能讓取x和x^MAX的數字個數儘量平均,即相等或者相差1。

確定s[i]的取值之後(有多少個s[i]取某個值x或者x^MAX),記第k個取值的s[i]共有nk個,於是最終的答案為

注意:要注意取值範圍,要開long long!【比賽中第一次提交就因為這個問題WA了……

【我的實現】

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4
#include <cmath> 5 #include <algorithm> 6 7 using namespace std; 8 #define MaxN 200030 9 10 long long s[MaxN]; 11 12 int main() 13 { 14 long long n, k; 15 long long i, j; 16 long long cnt, ans, tmp; 17 long long x; 18 long long MAX; 19 //scanf("%d%d", &n, &k); 20 cin >> n >> k; 21 MAX = (1<<(long long)k)-1; 22 s[0] = 0; 23 for(i = 1; i <= n; i++) 24 { 25 cin >> x; 26 s[i] = s[i-1] ^ x; 27 } 28 for(i = 0; i <= n; i++) 29 s[i] = min(s[i], MAX^s[i]); 30 sort(s, s+n+1); 31 cnt = 0; 32 ans = (n+1) * n / 2; 33 for(i = 0; i <= n; i++) 34 { 35 if(i == 0 || s[i] == s[i-1]) 36 cnt++; 37 else 38 { 39 if(cnt % 2) //奇數 40 { 41 tmp = cnt / 2; 42 ans -= tmp * (tmp-1) / 2; 43 tmp = cnt / 2 + 1; 44 ans -= tmp * (tmp-1) / 2; 45 } 46 else 47 { 48 tmp = cnt / 2; 49 ans -= tmp * (tmp-1); 50 } 51 cnt = 1; 52 } 53 } 54 if(cnt % 2) //奇數 55 { 56 tmp = cnt / 2; 57 ans -= tmp * (tmp-1) / 2; 58 tmp = cnt / 2 + 1; 59 ans -= tmp * (tmp-1) / 2; 60 } 61 else 62 { 63 tmp = cnt / 2; 64 ans -= tmp * (tmp-1); 65 } 66 cout<< ans; 67 return 0; 68 }
View Code

【評測結果】