Hdu 5833 Zhu and 772002(高斯消元解异或方程组)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5833

思路:

将每个数质因数分解,若该位质因数指数为偶数,则该位a[i]为0,否则该位a[i]为1(记a[i]为质因数分解后第i个质数所对应值)。

合法方案为积的各位质因子个数对应值a[i]异或值为0。

例3=3^1,4=2^2,则3*3*4对应:

2           3

0   (1 xor 1=0)

则可列方程组

a11x1+a12x2+...+a1nxn=0

a21x1+a22x2+...+a2nxn=0

...

an1x1+an2x2+...+annxn=0

a[i][j]表示第i个质数在第j个数所对应值(奇数个为1,偶数个为0)。

x[i]表示是否选择数字i,若选择为1,否则为0。

则ans=2^(n-r)-1(r为自由变量个数,减一表示不能全为0)

#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debu
using namespace std;
typedef long long LL;
const int maxn=350;
const int maxp=350;
const int maxx=2000;
const int mod=1e9+7;
struct Matrix
{
    int f[maxn][maxn];
};
Matrix e;
int v[maxx];
int n,m,q,k;
int a[maxn][maxp];
vector<int> prime;
int Guass(Matrix a,int n,int m)
{
    int i=1,j=1,k,r,u;
    while(i<=n&&j<=m)
    {
        r=i;
        for(k=i; k<=n; k++)
            if(a.f[k][j])
            {
                r=k;
                break;
            }
        if(a.f[r][j])
        {
            if(r!=i)
                for(k=0; k<=m+1; k++)
                    swap(a.f[r][k],a.f[i][k]);
            for(u=i+1; u<=n; u++)
                if(a.f[u][j])
                    for(k=i; k<=m+1; k++)
                        a.f[u][k]^=a.f[i][k];
            i++;
        }
        j++;
    }
    for(u=i; u<=n; u++)
        if(a.f[u][m+1]) return -1;
    return i-1;
}
void prepare()
{
    for(int i=2; i<maxx; i++)
    {
        if(!v[i])
        {
            prime.push_back(i);
            for(int j=i*i; j<maxx; j+=i) v[j]=1;
        }
    }
}
void change(int id,LL x)
{
    for(int i=0; i<prime.size(); i++)
    {
        while(x%prime[i]==0)
        {
            a[id][i+1]++;
            x/=prime[i];
            a[id][i+1]%=2;
        }
    }
}
LL pow_mod(LL a,LL b,LL mod)
{
   LL t=1,y=a;
   while(b)
   {
       if(b&1) t=(t*y)%mod;
       y=(y*y)%mod;
       b>>=1;
   }
   return t;
}
int main()
{
#ifdef debug
    freopen("in.in","r",stdin);
#endif // debug
    int t,cas=0;
    scanf("%d",&t);
    prepare();
    while(t--)
    {
        memset(a,0,sizeof(a));
        printf("Case #%d:\n",++cas);
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
        {
            LL x;
            scanf("%I64d",&x);
            change(i,x);
        }
        memset(e.f,0,sizeof(e.f));
        for(int i=0; i<prime.size(); i++)
            for(int j=1; j<=n; j++)
                e.f[i+1][j]=a[j][i+1];
        for(int i=0; i<prime.size(); i++) e.f[i+1][n+1]=0;
        int r=Guass(e,prime.size(),n);
        if(r==-1) printf("0\n");
        else printf("%I64d\n",pow_mod(2,n-r,mod)-1);
    }
    return 0;
}

时间: 2024-12-24 17:03:03

Hdu 5833 Zhu and 772002(高斯消元解异或方程组)的相关文章

BZOJ 3563 DZY Loves Chinese / BZOJ 3569 DZY Loves Chinese II 随机化+高斯消元解异或方程组

题目大意:给出一个无向图,问删掉k条边的时候,图是否联通. 思路:虽然我把这两个题放在了一起,但是其实这两个题可以用完全不同的两个解法来解决. 第一个题其实是DZY出错了...把每次的边数也异或了,那就直接用这个性质一个一个往后推就行了..最后一个暴力求一下.. 第二个题才是本意啊. 听到做法的时候我惊呆了.. 首先是将整个图中拆出一个树,那么所有边就分为树边和非树边.将所有非树边都加一个随机权值.树边的权值是所有能够覆盖它的非树边的权值的异或和. 把整个图拆开的充要条件是拆掉一条树边,同时将所

【BZOJ2466】【中山市选2009】树 高斯消元解异或方程组

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44356273"); } 题解: 参照此题解,也是我写的,俩题一样. [POJ1681]Painter's Problem 高斯消元,求最小∑系数的异或方程组 代码: #include <cmath> #include &

【poj1830-开关问题】高斯消元求解异或方程组

第一道高斯消元题目~ 题目:有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开.你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态.对于任意一个开关,最多只能进行一次开关操作.你的任务是,计算有多少种可以达到指定状态的方法.(不计开关操作的顺序)0<=N<=29 我们用样例来模拟一下: 我的高斯消元求解异或方程组模版: 1 int gauss

hdu-5833 Zhu and 772002(高斯消元)

题目链接: Zhu and 772002 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1006    Accepted Submission(s): 348 Problem Description Zhu and 772002 are both good at math. One day, Zhu wants to test the

poj2947(高斯消元解同模方程组)

题目链接:http://poj.org/problem?id=2947 题意:有n 种装饰物,m 个已知条件,每个已知条件的描述如下: p start enda1, a2......ap (1<= ai <= n)第一行表示从星期 start 到星期 end 一共生产了p 件装饰物 (工作的天数为end - start + 1 + 7*x, 加 7*x 是因为它可能生产很多周),第二行表示这 p 件装饰物的种类(可能出现相同的种类,即 ai = aj).规定每件装饰物至少生产3 天,最多生产9

高斯消元求解异或方程组

POJ1830 开关问题 对于解异或方程组,系数可以采用二进制压缩,如果系数太多可以使用bitset,但是如果少一点就可以使用下述的写法,更加简单快速 使用bitset的写法更正常的没什么区别,只是对应的消除变为异或操作,另外行变换也会更加简单 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; int a[100

[POJ1830]开关问题(高斯消元,异或方程组)

题目链接:http://poj.org/problem?id=1830 题意:中文题面,求的是方案数. 首先可以知道, 如果方案数不止一个的话,说明矩阵行列式值为0,即存在自由变元,由于变量只有两种状态,那么方案数就是2^自由变元数. 从起始状态到终止状态,只需要关心起始和终止哪些状态不一样就行,也就是翻转奇数次. 由于是倒推,所以开关的影响要反过来存. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long lon

POJ 1222-EXTENDED LIGHTS OUT(高斯消元求解异或方程组)

题目地址:POJ 1222 题意:有一个5*6的矩阵,每个位置都表示按钮和灯,1表示亮,0表示灭.每当按下一个位置的按钮,它和它周围灯的状态全部翻转(题目中给出如何影响),问在这样的一个方阵中按下哪些按钮可以把整个方阵都变成灭的,这时1表示按了,0表示没按. #include <stdio.h> #include <math.h> #include <string.h> #include <stdlib.h> #include <iostream>

2014多校第一场J题 || HDU 4870 Rating(DP || 高斯消元)

题目链接 题意 :小女孩注册了两个比赛的帐号,初始分值都为0,每做一次比赛如果排名在前两百名,rating涨50,否则降100,告诉你她每次比赛在前两百名的概率p,如果她每次做题都用两个账号中分数低的那个去做,问她最终有一个账号达到1000分需要做的比赛的次数的期望值. 思路 :可以直接用公式推出来用DP做,也可以列出210个方程组用高斯消元去做. (1)DP1:离散化.因为50,100,1000都是50的倍数,所以就看作1,2,20.这样做起来比较方便. 定义dp[i]为从 i 分数到达i+1