想不到,半年之後,居然遇到了重題!
首先證明乙個結論:選取後序列的異或最小值只可能為序列排序後相鄰元素的異或值的最小值。
證明:
設當前有 a≤b有了這個結論之後就好做了。≤c
a\le b\le c
a≤b≤
c ,現在只需證明 min(
a⊕b,
b⊕c)
≤a⊕c
\min(a\oplus b,b\oplus c)\le a\oplus c
min(a⊕
b,b⊕
c)≤a
⊕c即可。
因此 ∀a,
b,c∈
n,a≤
b≤c,
都有min(
a⊕b,
b⊕c)
≤a⊕c
\forall a,b,c\in n,a\le b\le c,\text\min(a\oplus b,b\oplus c)\le a\oplus c
∀a,b,c
∈n,a
≤b≤c
,都有min(a⊕
b,b⊕
c)≤a
⊕c。
先將 a
aa 從小到大排序。
設 f
if_i
fi 表示以 a
ia_i
ai 結尾的合法序列的個數。
那麼有狀態轉移方程
f i=
1+∑1
≤j
ai⊕a
j≥xf
jf_i=1+\sum_
void
qry(
int k,ll a,ll num)
void
inc(
int k,ll a,ll num)
int to=
trans
(a&num);if
(!son[k]
[to]
) son[k]
[to]
=++s;
inc(son[k]
[to]
,a,num>>1)
; sum[k]
=sum[son[k][0
]]+sum[son[k][1
]];if
(sum[k]
>=p) sum[k]
-=p;
}int
main()
--x,
sort
(a+1
,a+n+1)
;for
(int i=
1;i<=n;
++i)
f[++id]=1
,qry(1
,a[i]
,1ll
<<59)
,inc(1
,a[i]
,1ll
<<59)
,add
(ans,f[i]);
printf
("%d\n"
,ans)
;return0;
}
#include
#include
using
namespace std;
typedef
long
long ll;
#define fo(i,l,r) for(i=l;i<=r;++i)
#define m 20000005
#define n 300005
const
int p=
998244353
;ll x,a[n]
;int f[n]
,son[m][2
],sum[m]
,s=1
,cnt;
inline
void
add(
int&x,
int y)
inline
intaddi
(int x,
int y)
void
solve
(int k,ll now,ll num)
}void
inc(
int k,ll x,ll num)
int to=x&num?1:
0;if(
!son[k]
[to]
) son[k]
[to]
=++s;
inc(son[k]
[to]
,x,num>>1)
; sum[k]
=addi
(sum[son[k][0
]],sum[son[k][1
]]);
}int
main()
sort
(a+1
,a+n+1)
,--x;
fo(i,
1,n)
printf
("%d\n"
,ans)
;return0;
}
異或相關的雜題
連續多場 cf 都卡在 xor 題,並且以各不相同的方式寄了。不得不惡補一下這方面的處理技巧 codeforces 訪問有點慢,所以掛洛谷的題目鏈結 e 和 s 在玩博弈遊戲,e 先手 s 後手。給一棵 n 個節點的樹,節點的值包含 1,n 中的每乙個值。e 先隨便選擇乙個點,占領它 點 u s 只...
ZOJ 4057(異或 技巧題)
題意 找乙個最大的集合,使得這些任意兩個異或後的值都比最小的那個小。思路 這道題不需要01字典樹,2進製裡面2的次方的最高位都是1,所以只需要在2,4,8,16,區間放入小於上界的數即可。比如x小於4的時候,任意兩個異或起來絕對小於4,因為x小於4時與4最高位對應的是0,0 0 0,以此類推 最後暴...
異或運用 演算法題 缺失的數
題目 給出乙個包含 0 n 中 n 個數的序列,找出0 n 中沒有出現在序列中的那個數。public int findmissing int nums int result total 0 int result incomplete 0 for int i 0 i nums.length i for...