zoukankan      html  css  js  c++  java
  • HDU6865 杭电多校8 1011-Kidnapper's Matching Problem (线性基+KMP)

    HDU6865 杭电多校8 1011-Kidnapper's Matching Problem (线性基+KMP)

    题意:

    题意就是计算这个式子,[condition] 当(a_{i} ... a_{i+m-1}​) 与b数组满足匹配关系时为1。具体匹配关系指(a_{i} oplus b_{i} in 2^{S}_{⊕}​) 。其中 S 为输入的一组数,$ 2^{S}_{⊕}​$ 表示S数组所有任意子集的异或和结果的集合。

    题解:

    这里先放题解原文:

    具体就是先用 S 数组计算其线性基,得到$ 2^{S}_{⊕}$ 。 然后按题解的结论把a[], b[]数组中的数去掉线性基中有的位得到 (a`[ ] ,b`[ ])。然后找能够按题意匹配的位置 i ,当然按照题解结论,对匹配的那一段有 (a`[i] = b`[i]) 。 所以直接用KMP去处理就好了。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, n) for(int i = a; i <= n; ++ i)
    #define per(i, a, n) for(int i = n; i >= a; -- i)
    typedef long long ll;
    const int N = 2e6 + 105;
    const int mod = 1e9 + 7;
    const double Pi = acos(- 1.0);
    const ll INF = 1e18;
    const int G = 3, Gi = 332748118;
    ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    //
    
    const int maxbit = 62;		//maxbit不能太大
    
    struct L_B{
    	ll lba[maxbit], p[maxbit];
    	int cnt;
    	L_B(){
            memset(lba, 0, sizeof(lba));
            memset(p, 0, sizeof(p));
            cnt = 0;
        }
        
    	void Insert(ll val){		//插入
            for(int i = maxbit - 1; i >= 0; -- i)
                if(val & (1ll << i)){
                    if(!lba[i]){
                        lba[i] = val;
                        break;
                    }
                    val ^= lba[i];
                }
        }
    };
    // --------------线性基模板
    
    
    
    int T, n, m, k;
    ll a[N], b[N];
    int nxt[N];
    int vis[N];
    
    void get_next()
    {
        int i = 1, j = 0;
        nxt[1] = 0;
        while(i <= m){
            if(j == 0 || b[i] == b[j]){
                i ++, j ++, nxt[i] = j;
            }
            else j = nxt[j];
        }
    }
    
    void KMP()
    {
        get_next();
        int i = 0, j = 0;
        while(i <= n && j <= m){
            if(j == 0 || a[i] == b[j]) i++, j++;
            else j = nxt[j];
            
            if(j == m + 1){
                vis[i - m] = 1;
                j = nxt[j];
            }
        }
    }
    
    void init(){
        for(int i = 0; i <= n; ++ i){
            nxt[i] = 0; vis[i] = 0;
        }
    }
    
    int main()
    {
        scanf("%d",&T);
        while(T --){
            L_B lb;
            scanf("%d%d%d",&n,&m,&k);
            for(int i = 1; i <= n; ++ i) scanf("%d",&a[i]);
            for(int i = 1; i <= m; ++ i) scanf("%d",&b[i]);
            for(int i = 1; i <= k; ++ i){
                ll x; scanf("%lld",&x);
                lb.Insert(x);
            }
            for(int i = 1; i <= n; ++ i){
                for(int j = maxbit - 1; j >= 0; -- j){
                    if(a[i] & (1 << j)){
                        a[i] ^= lb.lba[j];
                    }
                }
            }
            for(int i = 1; i <= m; ++ i){
                for(int j = maxbit - 1; j >= 0; -- j){
                    if(b[i] & (1 << j)){
                        b[i] ^= lb.lba[j];
                    }
                }
            }
    
            init(); KMP();
            ll res = 0, temp = 1;
            for(int i = 1; i <= n - m + 1; ++ i){
                if(vis[i]) res = (res + temp) % mod;
                temp = temp * 2ll % mod;
            }
            printf("%lld
    ",res);
        }
        return 0;
    }
    
    
  • 相关阅读:
    kickstart自动化安装
    linux双网卡绑定
    作死实验,删除libc.so.6
    安装centos6及安装redhat6后的配置
    交换机、linux光衰查询
    ansible的简单使用
    linux安全配置学习
    vm的三种网络模式
    Recylerview的使用系列教程
    Android自定义组合控件
  • 原文地址:https://www.cnblogs.com/A-sc/p/13498671.html
Copyright © 2011-2022 走看看