Preliminary study of HDU5833 XOR equations

topic

topic link

answer

If the selected numbers are multiplied together to form a perfect square number, after this perfect square number is primed, the number of the same prime factors is an even number.

Based on this conclusion, we compare the number of candidates with each a [ i ] Do prime factorization (up to 303 different prime factors).

Then for each prime factor p , column one contains all n XOR equation of numbers, if a number has an odd number p , then the coefficient before this number should be 1, otherwise it should be 0. The right-hand side of the equation is always 0 because the square has an even number of prime factors.

We can list up to 303 XOR equations consisting of XOR equations, and we use the Gaussian elimination algorithm to solve this XOR equation system, assuming that the number of free elements to be solved is res.
Then the final answer is 2 r e s 1 indivual. ( Subtract the case of taking nothing ).

Summarize

When we find that this is a problem involving taking or not taking an element, and related to xor or parity, we have to think about the XOR equation system.

code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <bitset>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn = 307;
const int maxm = 307;
const ll mod = 1e9+7;
ll a[maxn];
bitset<maxn> ba[maxm];
int T,n,cas;
int primes[maxm];
int pc = 0;
int not_prime[2000];
int getprimes(){
    for(int i = 2;i <= 2000;++i){
        if(!not_prime[i]){
            primes[pc++] = i;
            for(int j = 2*i;j <= 2000;j += i)
                not_prime[j] = 1;
        }
    }
}
bool nofree[maxn];
int xor_gauss(int n,int m){
    /* 用于给定异或方程组消元
     * 返回自由变元的个数 n-j
     */
    memset(nofree,0,sizeof(nofree));
    int j = 0;
    for(int i = 0;i < n;++i){
        int sp = j;
        while(sp < m){
            if(ba[sp][i]){
                nofree[i] = true;
                break;
            }
            sp++;
        }
        if(sp < m){
            swap(ba[j],ba[sp]);
            for(int k = j+1;k < m;++k){
                if(ba[k][i]) ba[k] ^= ba[j];
            }
            ++j;
        }
    }
    //无解判定
    for(int k = j;k < m;++k){
        if(ba[k].count() == 1 && ba[k][n]) return -1;
    }
    return n-j;
}
int main(){
    getprimes();
    cin>>T;
    while(T--){
        for(int i = 0;i < maxm;++i) ba[i].reset();
        cin>>n;
        for(int i = 0;i < n;++i){
            scanf("%lld",&a[i]);
        }
        for(int i = 0;i < pc;++i){
            for(int j = 0;j < n;++j){
                int cc = 0;
                ll tmp = a[j];
                while(tmp % primes[i] == 0){
                    cc ^= 1;
                    tmp /= primes[i];
                }
                ba[i][j] = cc;
            }
        }
        int res = xor_gauss(n,pc);
        ll ans = 1;
        for(int i = 0;i < res;++i) ans = ans * 2 % mod;
        printf("Case #%d:\n%lld\n",++cas,ans-1);
    }
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325741357&siteId=291194637