2024牛客多校9-D-Luner XOR-FWT、湊式子

yoshinow2001發表於2024-08-14

link:https://ac.nowcoder.com/acm/contest/81604/D
題意:已知 \(n\) 元布林函式 \(f:\mathbb{Z}_2^n\to \mathbb{Z}_2\)\(\mathbb{Z}_2^n\) 上的一次多項式形如: \(g(x)=a_0 \oplus (a_1 x_1)\dots \oplus (a_n x_n)\) ,定義兩個函式的距離 \(d(f,g)=\sum_{x\in \mathbb{Z}_2^n} (f\oplus g)\) 。(1)對所有 \(2^{n+1}\) 個一次多項式,求其到 \(f\) 距離平方之和(2)求 \(d(f,g)\) 最小值。

\(1\leq n\leq 21\).


\(a_0\) 基本是湊數的。
只看 \(a_1,\dots,a_n\) ,意味著對所有 \(2^n\)\(a\),幾乎都要求出 \(d(f,g_a)\) 的值,題解給了一個很好的觀察:\(f,g\) 都是到 \(\mathbb{Z}_2\) 的函式,\((f\oplus g)=[f\neq g]=\frac{1}{2}-\frac{1}{2}(-1)^{f+g}\),則$$d(f,g)=2^{n-1}-\frac{1}{2}\sum_x (-1)^{f(x)+g(x)}$$
考察後面的式子,\(a_0=0\) 意味著沒有影響,\(a_0=1\) 則是乘 \(-1\),最後再處理,只看\(G(x)=\oplus (a_i x_i)=popcount(a\& x)\bmod 2=a\circ x\),這裡 \(a\circ x\) 就是異或卷積做FWT變換的時候用到的,回顧一下:
FWT 可以得到\(FWT[A]_i=\sum_{i\circ j=0} A_j-\sum_{i\circ j=1} A_j\).
在這裡,如果\(a\circ x=0\),則會有 \((-1)^f\) 的貢獻,否則是 \(-(-1)^f\) 的貢獻,剛好可以把 \((-1)^{f(x)}\) 作為 \(A(x)\),對其做一次異或的FWT,得到的序列就恰是後面的 \(\sum\)

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
int main(){
    fastio;
    int n;cin>>n;
    int mx=(1<<n),ans=0,mi=INF;
    vector<long long> f(mx);
    rep(i,0,mx-1){
        int x;cin>>x;
        if(x)f[i]=-1;
        else f[i]=1;
    }
    for(int x=2;x<=mx;x<<=1){
        int k=x>>1;
        for(int i=0;i<mx;i+=x)for(int j=0;j<k;j++){
            long long p=f[i+j],q=f[i+j+k];
            f[i+j]=p+q;f[i+j+k]=p-q;
        }
    }
    rep(i,0,mx-1){
        int x=(1<<(n-1))-(f[i]>>1);
        ans=(ans+(long long)x*x)%MOD;
        mi=min(mi,x);

        x=(1<<(n-1))+(f[i]>>1);
        ans=(ans+(long long)x*x)%MOD;
        mi=min(mi,x);
    }
    cout<<ans<<' '<<mi;
    return 0;
}

真是無比奇妙(這玩意真的不是對著FWT的性質,或者某個和FWT相關的研究出的題嗎)

相關文章