zoukankan      html  css  js  c++  java
  • CF1270I Xor on Figures

    有个矩阵(A),下标循环。给出个坐标集合(F)。每次可以选择一个点((i,j)),使(A_{i+x,j+y})异或(p)(p)为自己定的一个数,每次可以不同。

    问最少的操作次数。

    矩阵大小为(2^k*2^k)

    (kle 9,|F|le 99)

    (|F|)为奇数。


    感觉好像看过但是还是不会……看题解好像好简单啊怎么直接抽代就完事了。

    定义运算(A*B),表示((A*B)_{x,y}=sum_{i,j}A_{i,j}B_{x-i,y-j})

    于是题目相当于,找到(C)使得(C*F=A)。其中(C)的非零位置尽量少。

    以下证明(F)存在逆元,且(F^{-1}=F^{2^k-1})。于是(C=A*F^{2^k-1}),此时(C)唯一跟最小根本就没有关系。暴力算即可。

    观察到(F^2)中,有值的位置只有((2x_i,2y_i))。因为((x_i,y_i),(x_j,y_j),i eq j)的贡献会被算两次被抵消。于是(F^{2^k})中只有((0,0))处有值,并且这个值一定为(1),因为(|F|)为奇数。


    using namespace std;
    #include <bits/stdc++.h>
    #define K 9
    #define N (1<<K)
    #define ll long long
    int k,n;
    ll a[N][N];
    int m;
    struct DOT{
    	int x,y;
    } d[105];
    int main(){
    //	freopen("in.txt","r",stdin);
    	scanf("%d",&k);
    	n=1<<k;
    	for (int i=0;i<n;++i)
    		for (int j=0;j<n;++j)
    			scanf("%lld",&a[i][j]);
    	scanf("%d",&m);
    	for (int i=0;i<m;++i){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		--x,--y;
    		d[i]={x,y};
    	}
    	for (int t=0;t<k;++t){
    		static ll b[N][N];
    		memcpy(b,a,sizeof a);
    		memset(a,0,sizeof a);
    		for (int i=0;i<n;++i)
    			for (int j=0;j<n;++j)
    				for (int l=0;l<m;++l)
    					a[i+d[l].x&n-1][j+d[l].y&n-1]^=b[i][j];
    		for (int l=0;l<m;++l)
    			d[l]={d[l].x<<1&n-1,d[l].y<<1&n-1};
    	}
    	int ans=0;
    	for (int i=0;i<n;++i)
    		for (int j=0;j<n;++j)
    			ans+=(a[i][j]!=0);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    为什么 "auto a = 1;" 在C语言中可以编译通过?
    谈谈duilib
    软工第一次作业
    数独_个人项目
    统计Github项目信息
    字符串中的匹配之递归
    软工第0次作业
    c++浅拷贝与深拷贝(LeetCode669)
    修改xcode初始生成代码
    树上处理的问题总结
  • 原文地址:https://www.cnblogs.com/jz-597/p/14454036.html
Copyright © 2011-2022 走看看