給出n個數的集合a ,找出乙個子集s滿足s中的所有元素異或後為0(mod 1000000007),求∑|s|
線性基介紹
算每個元素出現在滿足要求的集合的次數,也就是每個元素對答案的貢獻。所以先求出線性基d1
對於線性基以外的元素,必然可以由線性基的異或和表示,所以完全為線性基外元素的異或和也仍然可以由線性基的異或和表示。所以,線性基外元素的貢獻為2n−
r−12^
2n−r−1
,共計n-r個。
而對於線性基內的元素,需要判斷該元素是否可代替,也就是說該元素是否能插入剩餘n-1個元素的線性基,只有插入時才會有貢獻。因為不是所有線性基的元素都是用來表示其他陣列中其他元素,有的線性基元素只是因為別人表示不了他,才被划進線性基里的。此時貢獻為2n−
r−12^
2n−r−1
因為在判斷線性基內元素時要求乙個新的線性基,而每次重新插入必然是超時的,現在考慮如何快速的求解。
從超時的插入中我們可以看出,非線性基元素是一定要插入的,所以不妨先求出非線性基元素的線性基d2,再在這個基礎上插入線性基元素,構成所求的線性基d3,再向d3中插入該元素判斷。
#include #define inf 0x3f3f3f3f
#define ll long long
#define pair pair#define re return
#define getlen(name,index) name[index].size()
#define mem(a,b) memset(a,b,sizeof(a))
#define make(a,b) make_pair(a,b)
#define push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index=star;index--)
using namespace std;
const int maxn=1e5+7;
const int mod=1e9+7;
templatevoid _deb(const char *name,t val)
return pow[record]=res % mod;
}linerbase d1,d2,d3;
int lenr,lenot;
ll store[maxn],r[maxn],ot[maxn];
setlb;
int main()
rep(i,0,n)else
}ll amount=(n-d1.size());
for(register int i=0;i除此之外,還有更加快速的方法判斷。在判斷線性基內元素時,列舉所有可替代元素。但是我還沒看懂,看懂了再補。
2019牛客多校第一場 H XOR
複習線性基複習了好久。這題的關鍵是把異或為0的集合的大小之和轉化為乙個數字會在多少個異或為0的集合 現,然後每個數字的這個值加起來就行。先求乙個線性基,其中插入了r個數字,那麼剩下的n r個數字的任意組合異或都可以由線性基中的一些數異或表示,那麼它們異或起來就為0.考慮線性基外的乙個數字,我先欽定乙...
2019牛客多校第一場
看到這裡我還能說什麼呢?自己慢慢證吧 就是這個 而 了 大佬們的結論是 三角形面積的22倍。我.手動膜拜。不會證.while true try x1,y1,x2,y2,x3,y3 map int,input split s abs x1 y2 x2 y1 x2 y3 x3 y2 x3 y1 x1 y...
2019 牛客多校 第一場
a 題意 就是兩個陣列,找最大的p,使對於1到p的所有子區間都保證最小值的下標相同 題解 每次往後加乙個值 第i 1位 都會多出 i 個區間,當a i 1 大於max a 1 a i 時沒有影響,當a i 小於max a 1 a i 時,因為a i 1 的加入會導致區間的rmq l到r 的 最小值的...