O(nm2n) 得到 70 分是怎么回事呢?O(nm2n) 相信大家都很熟悉,但是 O(nm2n) 得到 70 分是怎么回事呢,下面就让小编带大家一起了解吧。
O(nm2n) 得到 70 分,其实就是
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+5, M=5e3+5, MOD=1e9+7;
int n, m, q;
bitset<M> a[N], b[N];
unordered_map<bitset<M>, int> cnt[N];
unordered_map<bitset<M>, int>::iterator it;
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m>>q;
for(int i=1; i<=n; i++) cin>>a[i];
for(int i=1; i<=q; i++) cin>>b[i];
cnt[0][a[0]]=1;
for(int i=1; i<=n; i++)
{
for(it=cnt[i-1].begin(); it!=cnt[i-1].end(); it++)
{
cnt[i][(*it).first&a[i]]=(cnt[i][(*it).first&a[i]]+(*it).second)%MOD;
cnt[i][(*it).first|a[i]]=(cnt[i][(*it).first|a[i]]+(*it).second)%MOD;
}
}
for(int i=1; i<=q; i++) cout<<cnt[n][b[i]]<<endl;
return 0;
}
大家可能会很惊讶 O(nm2n) 怎么会得到 70 分呢?但事实就是这样,小编也感到非常惊讶。
这就是关于暴力做法得到 70 分的事情了,大家有什么想法呢,欢迎在评论区告诉小编一起讨论哦!
符号说明:下文的串均默认为长度为 m 的 01 串;集合 X 的大小或者串 X 中 1 的数量均记为 #X;变量 ⊕ 代表某种位运算;当串 X 中 1 的位置在 Y 中均为 1,那么就记 X⊆Y。
(尽管看起来有点滥用符号,但实际上这里只是为了避免将串转成集合描述的麻烦,下文用到的串和集合其实没啥区别。)
记
Sn=#{0⊕0a1⊕1a2⋯⊕n−1an∣⊕i∈{∧,∨}}
目标是去算这个 Sn 的上界。
跳过 observation,这里直接给出欲证明的性质
∀x,y∈Sn,#x≤#y⟺x⊆y
其中 ⟸ 根据定义即得,所以下文主要考虑 ⟹。
对 n 归纳。n=0 时显然;假设 n=i−1 时成立,考虑 n=i,用反证法,假设
∃p,q∈Si−1,#(p⊕pai)≤#(q⊕qai)
使得
(p⊕pai)⊆(q⊕qai)
上式蕴含了 (p⊕pai)=(q⊕qai)。分类讨论:
- (⊕p,⊕q)=(∧,∧) 时,由归纳假设,可以分两类讨论
- p⊆q,则 (p∧ai)⊆(q∧ai),矛盾;
- q⊆p,则 (q∧ai)⊆(p∧ai),又因为 #(p∧ai)≤#(q∧ai),从而 (p∧ai)=(q∧ai),矛盾;
- (⊕p,⊕q)=(∧,∨) 时,由 (p∧ai)⊆ai⊆(q∨ai),矛盾;
- (⊕p,⊕q)=(∨,∧) 时,由 (q∧ai)⊆ai⊆(p∨ai),又因为 #(p∨ai)≤#(q∧ai),从而 (q∧ai)=(p∨ai),矛盾;
- (⊕p,⊕q)=(∨,∨) 时,由归纳假设,可以分两类讨论
- p⊆q,则 (p∨ai)⊆(q∨ai),矛盾;
- q⊆p,则 (q∨ai)⊆(p∨ai),又因为 #(p∨ai)≤#(q∨ai),从而 (p∨ai)=(q∨ai),矛盾;
由数学归纳法得证。
由上面证明的结论即可直接推得
∀x,y∈Sn,#x=#y⟺x=y
因此对于 #x=0,1,⋯,m,对应的 x 最多只有一个。因此
#Sn≤m+1
这就证明了这个做法是 O(nm2/w) 的。