线性基例题

最大异或和,第k小异或和

  • 最大异或和

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    #include<bits/stdc++.h>
    #define INIT(a,b) memset(a,b,sizeof(a))
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    #define repd(i,a,b) for(int i=a;i>=b;--i)
    #define S(d) scanf("%d",&d)
    #define Sll(d) scanf("%lld",&d)
    #define P(d) printf("%d",d)
    #define Pll(d) printf("%lld",d)
    using namespace std;
    const int inf=0x3f3f3f3f;
    const int N=100+7;
    const int M=2e6+7;
    const int mod=1e9+7;
    ll d[N],a[N];
    int n;
    void add(ll x){
    repd(i,51,0)
    if(x&(1ll<<i)){
    if(d[i]) x^=d[i];
    else {
    d[i]=x;
    //"高斯消元,使得对于任意存在于线性基的二进制位i,至多只有一个b[j]满足第i位为 1。可求第k小异或和,最大就全异或"
    repd(k,i-1,0) if(d[k]&&(d[i]&(1ll<<k))) d[i]^=d[k];
    rep(k,i+1,51) if(d[k]&(1ll<<i)) d[k]^=d[i];
    break;
    }
    }
    }
    ll ans(){
    ll res=0;
    repd(i,51,0) res^=d[i];
    return res;
    }
    int main(){
    S(n);
    rep(i,1,n) {
    Sll(a[i]);
    add(a[i]);
    }
    Pll(ans());
    return 0;
    }
  • 第k小异或和

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    #include<bits/stdc++.h>
    #define INIT(a,b) memset(a,b,sizeof(a))
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    #define repd(i,a,b) for(int i=a;i>=b;--i)
    #define S(d) scanf("%d",&d)
    #define SLL(d) scanf("%lld",&d)
    #define P(d) printf("%d\n",d)
    #define PLL(d) printf("%lld\n",d)
    using namespace std;
    const int inf=0x3f3f3f3f;
    const int N=1e4+7;
    const int M=2e6+7;
    const int mod=1e9+7;
    int t,n,q,tot;
    ll a[N],d[100],k;
    void add(ll x){
    repd(i,61,0)
    if(x&(1ll<<i)){
    if(d[i]) x^=d[i];
    else {
    d[i]=x;
    tot++;
    repd(k,i-1,0) if(d[k]&&(d[i]&(1ll<<k))) d[i]^=d[k];
    rep(k,i+1,61) if(d[k]&(1ll<<i)) d[k]^=d[i];
    break;
    }

    }
    }
    ll ans(ll k){
    if(tot<n)k--;//当tot<n时整体可异或出0,但线性基里面不会
    if(k>=(1ll<<tot))return -1;//超过能异或出的数的个数上限
    ll ans=0;
    //k的第i位为1时,异或第i个线性基中的元素
    rep(i,0,61){
    if(d[i]){
    if(k&1) ans^=d[i];
    k>>=1;
    }
    }
    return ans;
    }
    int main(){
    S(t);
    rep(Case,1,t){
    printf("Case #%d:\n", Case);
    INIT(d,0);tot=0;
    S(n);
    rep(i,1,n) {
    SLL(a[i]);
    add(a[i]);
    }
    S(q);
    while(q--){
    SLL(k);
    PLL(ans(k));
    }
    }
    return 0;
    }
  • 给出一个数,求在不去重异或集合中的位置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    #pragma GCC optimize(3)
    #include<bits/stdc++.h>
    #define INIT(a,b) memset(a,b,sizeof(a))
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    #define repd(i,a,b) for(int i=a;i>=b;--i)
    #define S(d) scanf("%d",&d)
    #define SLL(d) scanf("%lld",&d)
    #define P(d) printf("%d\n",d)
    #define PLL(d) printf("%lld\n",d)
    using namespace std;
    const int inf=0x3f3f3f3f;
    const int N=1e5+7;
    const int M=2e6+7;
    const int mod=10086;
    const int Size=30;
    int n,q,a[N],d[100],num=0;
    int qpow(int x,int n){
    int ans=1;
    x%=mod;
    while(n){
    if(n&1) (ans*=x)%=mod;
    (x*=x)%=mod;
    n>>=1;
    }
    return ans%mod;
    }
    void add(int x){
    repd(i,Size,0)
    if(x>>i & 1){
    if(d[i]) x^=d[i];
    else {
    num++;
    d[i]=x;
    break;
    }
    }
    }
    vector<int> vec;
    int main(){
    S(n);
    rep(i,1,n){
    S(a[i]);
    add(a[i]);
    }
    S(q);
    int ans=0;
    rep(i,0,Size)
    if(d[i]) vec.push_back(i);
    rep(i,0,vec.size()-1)
    if(q>>vec[i] & 1)
    (ans+=(1<<i))%=mod;
    P((qpow(2,(n-num))%mod*ans%mod+1)%mod);
    return 0;
    }
### 使用单纯形法解决线性规划问题的示例 #### 示例题目 考虑如下线性规划问题: 最大化 \( Z = 3x_1 + 5x_2 \) 受制于: \[ \begin{align*} x_1 & \leq 4 \\ 2x_2 & \leq 12 \\ 3x_1 + 2x_2 & \leq 18 \\ x_1, x_2 & \geq 0 \end{align*} \] 引入松弛变量 \( x_3, x_4, x_5 \),使得不等式变为等式形式。 初始模型可以表示为: \[ \begin{align*} Z &= 3x_1 + 5x_2 + 0x_3 + 0x_4 + 0x_5 \\ s.t.\quad x_1 + x_3 &= 4 \\ 2x_2 + x_4 &= 12 \\ 3x_1 + 2x_2 + x_5 &= 18 \\ x_i & \geq 0,\ i=1,2,...,5 \end{align*} \] #### 初始单纯形表 | 基 | \( b \) | \( x_1 \) | \( x_2 \) | \( x_3 \) | \( x_4 \) | \( x_5 \) | |--|-----------|-----------|-----------|-----------| | \( x_3 \) | 4 | 1 | 0 | 1 | 0 | 0 | | \( x_4 \) | 12 | 0 | 2 | 0 | 1 | 0 | | \( x_5 \) | 18 | 3 | 2 | 0 | 0 | 1 | | \( z_j-c_j \)| 0 |-3 |-5 | 0 | 0 | 0 | 由于存在负检验数,继续迭代直到所有检验数非负为止[^1]。 #### 第一次迭代 选取最大负检验数对应的列作为入基变量(\( x_2 \)),并计算最小比确定离基变量(\( x_4 \))。更新后的表格如下所示: | 基 | \( b \) | \( x_1 \) | \( x_2 \) | \( x_3 \) | \( x_4 \) | \( x_5 \) | |-------|---------|-----------|-----------|-----------|-----------|-----------| | \( x_3 \) | 4 | 1 | 0 | 1 | 0 | 0 | | \( x_2 \) | 6 | 0 | 1 | 0 | 0.5 | 0 | | \( x_5 \) | 6 | 3 | 0 | 0 | -1 | 1 | | \( z_j-c_j \) | 30 | -3 | 0 | 0 | 2.5 | 0 | 再次检查检验数,发现仍有一个负,因此需进一步迭代[^2]。 #### 第二次迭代 这次选择 \( x_1 \) 作为新的入基变量,并通过最小比得到 \( x_3 \) 将被替换。最终得到最优解: | 基 | \( b \) | \( x_1 \) | \( x_2 \) | \( x_3 \) | \( x_4 \) | \( x_5 \) | |--|-----------|-----------|-----------| | \( x_1 \) | 4/3 | 1 | 0 | 1/3 | 0 | 0 | | \( x_2 \) | 6 | 0 | 1 | 0 | 0.5 | 0 | | \( x_5 \) | 2 | 0 | 0 | -1 | -1 | 1 | | \( z_j-c_j \) | 38 | 0 | 0 | 1 | 2.5 | 0 | 此时所有的检验数均为正,表明已经找到了最优解:\( (x_1,x_2)=(4/3,6)\), 对应的目标函数为 \( Z_{max}=38 \).
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值