zoukankan      html  css  js  c++  java
  • CodeForces 1270I Xor on Figures

    CodeForces 1270I Xor on Figures

    https://codeforces.com/contest/1270/problem/I

    有一个 (2^k imes 2^k(1 le k le 9)) 的网格,其中 ((i,j)) 位置上的数字为 (a_{i,j}(0 le a_{i,j} < 2^{60})) .

    这个网格是循环的,即 ((i,2^k)) 的右边是 ((i,1)) , ((2^k,i)) 的下面是 ((1,i))

    有一个网格图(不一定联通) (F) ,它包含 (t) 个两两不同的格子(((1 le t le min{99,4^k}))(t) 为奇数) ((x_1,y_1),(x_2,y_2),cdots,(x_t,y_t)(1 le x_i,y_i le 2^k)) .

    一次操作可以选择一个格子 ((x,y)(1 le x,y le 2^k)) 和一个数字 (p) ,然后令所有 ((x+x_i mod 2^k,y+y_i mod 2^k)(1le i le t)) 上的数字异或 (p) .

    问至少需要多少次操作令所有格子中的数 (=0) .若不存在,输出 (-1)

    Tutorial

    https://www.luogu.com.cn/problem/solution/CF1270I

    定义新矩阵乘法 (A imes B =C) ,其中

    [C(x,y) = sum_{a=0}^{2^k-1} sum_{b=0}^{2^k-1} A(a,b)B(x-a mod 2^k,y-b mod 2^k) ]

    则我们需要的就是找到是否存在这样一个矩阵 (C) ,满足 (C imes F = A) ,且 (C) 中非零数的位置最少.

    假如我们可以找到 (F) 在新矩阵乘法意义下面的逆元.那么可以证明 (C) 是存在且唯一的.

    考虑 (F imes F) 的形状,其中有贡献的位置是 ((x_i+x_j mod 2^k,y_i+y_j mod 2^k)(1 le i,j le t)) 的形式.考虑若 (i ot= j) 那么 ((i,j),(j,i)) 分别贡献一次后这个位置上的数就会变为 (0) .

    所以最后 (F imes F) 的所有非零位置就是 ((2x_i mod 2^k,2y_i mod 2^k)) .

    那么 (F^{2^k}) 的所有非零位置就是 ((2^kx_i mod 2^k,2^ky_i mod 2^k)=(0,0)) ,而由于 (t) 是奇数,所以总是有奇数个 (1) ,所以 ((0,0)) 位置上最后为 (1) .而这相当于在新矩阵乘法意义下的单位矩阵 (I)

    [F^{2^k} = I \ F^{2^k-1}=F^{-1} ]

    [C=A imes F^{-1} = A imes F^{2^k-1} = A imes prod_{i=0}^{k-1} F^{2^i} ]

    由于 (F) 中的非零位置只有 (t) 个,所以一次新矩阵乘法的复杂度是 (O(4^kt)) 的.

    总时间复杂度 (O(kt4^k))

    Code

    #include <cassert>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <vector>
    #define fi first
    #define se second
    using namespace std;
    inline char nc()
    {
        static char buf[100000],*l=buf,*r=buf;
        return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
    }
    template<class T> void read(T &x)
    {
        x=0; int f=1,ch=nc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();}
        while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=nc();}
        x*=f;
    }
    typedef long long ll;
    typedef pair<int,int> pii;
    const int maxk=9;
    const int maxn=1<<maxk;
    const int maxt=99;
    int k;
    int n;
    int t;
    ll a[2][maxn][maxn];
    pii F[maxt];
    inline int add(int x) {return x>=n?x-n:x;} 
    inline int sub(int x) {return x<0?x+n:x;}
    int main()
    {
        // freopen("in.txt","r",stdin);
        read(k),n=1<<k;
        int cur=0;
        for(int i=0;i<n;++i) for(int j=0;j<n;++j)
        {
            read(a[cur][i][j]);
        }
        read(t);
        for(int i=0;i<t;++i)
        {
            read(F[i].fi),read(F[i].se);
        }
        for(int i=0;i<k;++i)
        {
            cur^=1;
            memset(a[cur],0,sizeof(a[cur]));
            for(int x=0;x<n;++x) for(int y=0;y<n;++y)
            {
                for(int j=0;j<t;++j)
                {
                    a[cur][x][y]^=a[cur^1][sub(x-F[j].fi)][sub(y-F[j].se)];
                }
            }
            for(int j=0;j<t;++j)
            {
                F[j].fi=add(F[j].fi<<1);
                F[j].se=add(F[j].se<<1);            
            }
        }
        int an=0;
        for(int x=0;x<n;++x) for(int y=0;y<n;++y)
        {
            if(a[cur][x][y]) ++an;
        }
        printf("%d
    ",an);
        return 0;
    }
    
  • 相关阅读:
    0593. Valid Square (M)
    0832. Flipping an Image (E)
    1026. Maximum Difference Between Node and Ancestor (M)
    0563. Binary Tree Tilt (E)
    0445. Add Two Numbers II (M)
    1283. Find the Smallest Divisor Given a Threshold (M)
    C Primer Plus note9
    C Primer Plus note8
    C Primer Plus note7
    C Primer Plus note6
  • 原文地址:https://www.cnblogs.com/ljzalc1022/p/13031383.html
Copyright © 2011-2022 走看看