n
nn 個數,求子集內所有數異或為 0
00 的所有子集大小之和
考慮每個值對答案的貢獻
首先對 n
nn 個數消一次元,得到 r
rr 個基
對於剩下 n−r
n-rn−
r 個數,每個數的貢獻是 2n−
r−12^
2n−r−1
因為對於其中每個數,剩下 n−r
−1
n-r-1
n−r−
1 個數可選可不選,而且加到 r
rr 個基後異或一定為 0
00昨天晚上洗澡的時候突然想通!!
為什麼可以這麼計算貢獻???
因為對於剩下的 n−r
n-rn−
r 個數的任意一種組合
在 r
rr 個基里 有且僅有 一組基能使得它們全部異或為 0
00然後求 r
rr 個基的貢獻
列舉其中每個基,對剩下(n−
1)
(n-1)
(n−1
)個數消元,設基的大小為 ∣d∣
|d|∣d
∣則列舉的這個基的貢獻為 2n−
∣d∣−
12^
2n−∣d∣
−1乙個優化點在於對(n−
1)
(n-1)
(n−1
)個數消元時,可以先預處理 n−r
n-rn−
r 個數的線性基
然後將 r−1
r-1r−
1 個數插入到該線性基即可
觀察可發現 ∣d∣
==
r|d| == r
∣d∣==r
!!!根據線性基的性質,乙個序列可以有多個線性基,且他們的表示結果是相同的
並且這些線性基中數字的個數也相同,即等價
所以如果列舉的值不能被插入剩餘 n−1
n-1n−
1 個數的線性基中,則該線性基就是這 n
nn 個數的線性基,即 rrr
最後時間複雜度為: o(64
n+64
3)
o(64n + 64^3)
o(64n+
643)
#include#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
//#pragma gcc optimize(3,"ofast","inline")
using namespace std;
typedef long long ll;
using pii = pair ;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
ll n, a[maxn], b[maxn], c[maxn];
ll cntb, cntc, cnt, r[maxn], ans;
struct lb
bool insert(ll x)
return ret;
}int main()
if(n-cnt) ans = 1ll * cntb * qpow(2, n-cnt-1) % mod;
for(int i=1; i<=cntb; i++)
if(b.insert(b[i]))
c[++cntc] = b[i];
for(int i=1; i<=cnt; i++)
printf("%lld\n", ans);
}}
2019牛客多校第一場H XOR 線性基
給出n個數的集合a 找出乙個子集s滿足s中的所有元素異或後為0 mod 1000000007 求 s 線性基介紹 算每個元素出現在滿足要求的集合的次數,也就是每個元素對答案的貢獻。所以先求出線性基d1 對於線性基以外的元素,必然可以由線性基的異或和表示,所以完全為線性基外元素的異或和也仍然可以由線性...
2019牛客多校第一場 H XOR
複習線性基複習了好久。這題的關鍵是把異或為0的集合的大小之和轉化為乙個數字會在多少個異或為0的集合 現,然後每個數字的這個值加起來就行。先求乙個線性基,其中插入了r個數字,那麼剩下的n r個數字的任意組合異或都可以由線性基中的一些數異或表示,那麼它們異或起來就為0.考慮線性基外的乙個數字,我先欽定乙...
2019牛客暑期多校第一場H(線性基)
首先,貼一下大佬的部落格 真 大佬 下面的題解也是大佬的,我只是按照我的理解理解了一下.其次,再了解一下線性基。很多情況下,只要有關異或運算和求最值,就可以用到線性基。線性基有很多很好的性質,比如說如果有很多個數,我們可以構出這些數的線性基,那麼這個線性基可以通過互相xor,能夠構出原來的數可以相互...