zoukankan      html  css  js  c++  java
  • CF895C Square Subsets [线性基]

    线性基的题…

    考虑平方数只和拆解质因子的个数的奇偶性有关系

    比如说你 (4)(16) 的贡献都是一样的。因为

    (4 = 2^2 , 16 = 2^4)

    (2)(4) 奇偶性相同

    然后考虑如何线性基,不难想到,二进制可以表示奇偶性,
    所以异或和每一位是0的时候就是一个平方数了。

    我们考虑把 线性基的元素设为 (|S|)

    那么你手头只剩下 (n-|S|) 个数字还可以被线性基表示的。

    如果可以表示,那么说明了这些 (2^{n-|S|}-1) 个子集异或和都可以和线性基拼凑成0

    所以目标答案就是 (2^{n-|S|}-1)

    
    // by Isaunoya
    #include <bits/stdc++.h>
    using namespace std;
    
    #define rep(i, x, y) for (register int i = (x); i <= (y); ++i)
    #define Rep(i, x, y) for (register int i = (x); i >= (y); --i)
    #define int long long
    
    const int _ = 1 << 21;
    struct I {
    	char fin[_], *p1 = fin, *p2 = fin;
    	inline char gc() {
    		return (p1 == p2) && (p2 = (p1 = fin) + fread(fin, 1, _, stdin), p1 == p2) ? EOF : *p1++;
    	}
    	inline I& operator>>(int& x) {
    		bool sign = 1;
    		char c = 0;
    		while (c < 48) ((c = gc()) == 45) && (sign = 0);
    		x = (c & 15);
    		while ((c = gc()) > 47) x = (x << 1) + (x << 3) + (c & 15);
    		x = sign ? x : -x;
    		return *this;
    	}
    	inline I& operator>>(double& x) {
    		bool sign = 1;
    		char c = 0;
    		while (c < 48) ((c = gc()) == 45) && (sign = 0);
    		x = (c - 48);
    		while ((c = gc()) > 47) x = x * 10 + (c - 48);
    		if (c == '.') {
    			double d = 1.0;
    			while ((c = gc()) > 47) d = d * 0.1, x = x + (d * (c - 48));
    		}
    		x = sign ? x : -x;
    		return *this;
    	}
    	inline I& operator>>(char& x) {
    		do
    			x = gc();
    		while (isspace(x));
    		return *this;
    	}
    	inline I& operator>>(string& s) {
    		s = "";
    		char c = gc();
    		while (isspace(c)) c = gc();
    		while (!isspace(c) && c != EOF) s += c, c = gc();
    		return *this;
    	}
    } in;
    struct O {
    	char st[100], fout[_];
    	signed stk = 0, top = 0;
    	inline void flush() {
    		fwrite(fout, 1, top, stdout), fflush(stdout), top = 0;
    	}
    	inline O& operator<<(int x) {
    		if (top > (1 << 20)) flush();
    		if (x < 0) fout[top++] = 45, x = -x;
    		do
    			st[++stk] = x % 10 ^ 48, x /= 10;
    		while (x);
    		while (stk) fout[top++] = st[stk--];
    		return *this;
    	}
    	inline O& operator<<(char x) {
    		fout[top++] = x;
    		return *this;
    	}
    	inline O& operator<<(string s) {
    		if (top > (1 << 20)) flush();
    		for (char x : s) fout[top++] = x;
    		return *this;
    	}
    } out;
    #define pb emplace_back
    #define fir first
    #define sec second
    
    template < class T > inline void cmax(T & x , const T & y) {
    	(x < y) && (x = y) ;
    }
    template < class T > inline void cmin(T & x , const T & y) {
    	(x > y) && (x = y) ;
    }
    
    int ans = 0 ;
    int p[30] ;
    int pri[30] = { 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29 , 31 , 37 , 41 , 43 , 47 , 53 , 59 , 61 , 67 } ;
    void ins(int x) {
    	for(int i = 19 ; ~ i ; i --) {
    		if(x & (1 << i)) {
    			if(! p[i]) {
    				p[i] = x ;
    			}
    			x ^= p[i] ;
    		}
    	}
    }
    const int mod = 1e9 + 7 ;
    int qpow(int x , int y) {
    	int ans = 1 ;
    	for( ; y ; y >>= 1 , x = x * x % mod) 
    		if(y & 1) ans = ans * x % mod ;
    	return ans ;
    }
    signed main() {
    #ifdef _WIN64
    	freopen("testdata.in" , "r" , stdin) ;
    #endif
    	int n ;
    	in >> n;
    	rep(i , 1 , n) {
    		int x ;
    		in >> x ;
    		int res = 0 ;
    		rep(j , 0 , 18) {
    			if(x % pri[j] == 0) {
    				int now = 0 ; 
    				while(x % pri[j] == 0) {
    					x /= pri[j] ;
    					now ^= 1 ;
    				}
    				res ^= (now << j) ;
    			}
    		}
    		ins(res) ;
    	}
    	for(int i = 19 ; ~ i ; i --) if(p[i]) n -- ;
    	out << ( qpow(2 , n) - 1 ) % mod << '
    ' ;
    	return out.flush(), 0;
    }
    
    
  • 相关阅读:
    SQL优化——union与union all 、left join 和 inner join 及 内连接
    用jdk自带工具jvisualvm查看系统内存使用情况
    不重启也能清理catalina.out日志的方法
    自己用crontab弄个定时任务备份日志重启项目
    三层架构的一点理解以及Dapper一对多查询
    Nuget包添加文件
    WPF启动流程-自己手写Main函数
    WPF实现手势解锁
    VS提交码云权限问题
    Json转Dictionary
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12186725.html
Copyright © 2011-2022 走看看