• Yahoo Programming Contest 2019.E.Odd Subrectangles(思路 线性基)


    题目链接


    (Description)

    给定一个(n imes m)(01)矩阵。求任意选出(r)行、(c)列(共(2^{n+m})种方案),使得这(r)(c)列的交的位置的(r imes c)个数的和为奇数,的方案数有多少。
    (...我也不知道怎么就表述成这样了,反正挺好理解)
    (n,mleq300)

    (Solution)

    假设已经确定了选择某些行,然后把每一行(m)个数看做一个(m)位二进制数。
    如果这些行异或和为(0),那怎么选列也不行。
    否则每一列异或这些行是(0)还是(1)是确定的。假设有(a)列异或后为(1)(b)列异或后为(0)(a+b=m)。我们要从(a)中选出奇数个,从(b)中随便选,那么方案数是(2^{a-1}cdot2^b=2^{m-1})(从(n)中选出奇数个数的方案数。。(C_n^1+C_n^3+C_n^5+...=frac{2^n}{2}=2^{n-1}))。
    也就是不管行怎么选,只要异或和不为(0),列就有(2^{m-1})种方案。
    异或和不为(0)的方案数=(2^n-)异或和为(0)的方案数。异或和为(0)的方案数可以用线性基求,是(2^{n-r})(n)是元素总数,(r)是矩阵的秩,也就是线性基中的元素个数),所以答案就是((2^n-2^{n-r})cdot2^{m-1})
    这里线性基插入还是一样的,把一行看做(m)位数就好了。

    复杂度(O(n^3))(O(frac{n^3}{w}))


    //7ms	896KB
    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define gc() getchar()
    #define mod 998244353
    typedef long long LL;
    const int N=305;
    
    int A[N][N],B[N][N];
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-48,c=gc());
    	return now;
    }
    inline int FP(int x,int k)
    {
    	int t=1;
    	for(; k; k>>=1,x=1ll*x*x%mod)
    		if(k&1) t=1ll*t*x%mod;
    	return t;
    }
    
    int main()
    {
    	int n=read(),m=read();
    	for(int i=1; i<=n; ++i)
    		for(int j=1; j<=m; ++j) A[i][j]=read();
    	int r=0;
    	for(int i=1; i<=n; ++i)
    		for(int j=1; j<=m; ++j)
    			if(A[i][j])//x>>j&1
    			{
    				if(B[j][j]) for(int k=j; k<=m; ++k) A[i][k]^=B[j][k];
    				else
    				{
    					for(int k=j; k<=m; ++k) B[j][k]=A[i][k];
    					++r; break;
    				}
    			}
    	printf("%d
    ",(FP(2,n+m-1)+mod-FP(2,n-r+m-1))%mod);
    
    	return 0;
    }
    

    bitset优化:

    //5ms	256KB
    #include <cstdio>
    #include <cctype>
    #include <bitset>
    #include <algorithm>
    #define gc() getchar()
    #define mod 998244353
    typedef long long LL;
    const int N=305;
    
    std::bitset<N> A[N],B[N];
    
    inline int read()
    {
    	int now=0;register char c=gc();
    	for(;!isdigit(c);c=gc());
    	for(;isdigit(c);now=now*10+c-48,c=gc());
    	return now;
    }
    inline int FP(int x,int k)
    {
    	int t=1;
    	for(; k; k>>=1,x=1ll*x*x%mod)
    		if(k&1) t=1ll*t*x%mod;
    	return t;
    }
    
    int main()
    {
    	int n=read(),m=read();
    	for(int i=1; i<=n; ++i)
    		for(int j=1; j<=m; ++j) A[i][j]=read()==1;
    	int r=0;
    	for(int i=1; i<=n; ++i)
    		for(int j=1; j<=m; ++j)
    			if(A[i][j])//x>>j&1
    			{
    				if(B[j][j]) A[i]^=B[j];
    				else
    				{
    					B[j]=A[i];
    					++r; break;
    				}
    			}
    	printf("%d
    ",(FP(2,n+m-1)+mod-FP(2,n-r+m-1))%mod);
    
    	return 0;
    }
    
  • 相关阅读:
    10.聚焦爬虫和通用爬虫的区别
    ethereum(以太坊)(基础)--容易忽略的坑(三)
    ethereum(以太坊)(基础)--容易忽略的坑(二)
    ethereum(以太坊)(基础)--容易忽略的坑(一)
    jQuery(四)--HTTP请求
    jQuery(三)HTML
    jQuery(一)初识
    jQuery(二)事件
    ethereum Pet Shop
    web3.js_1.x.x--API(一)event/Constant/deploy/options
  • 原文地址:https://www.cnblogs.com/SovietPower/p/10389645.html
Copyright © 2020-2023  润新知