高斯消元HDU-3364 Lanterns

来源:互联网 发布:电商商品推荐算法 编辑:程序博客网 时间:2024/05/18 06:07


高斯消元模板(有多个解。无解输出“零”,有解输出“2^自由元的个数”)

int luf[SIZE_A][SIZE_A],B[SIZE_A][SIZE_A];int n,m;long long Gauss(){    int cnt = 0;    for (int i = 0; i < m; i++){//每个开关代表的就是未知数,i代表每个多项式前面的系数        int j;        for (j = cnt; j < n; j++)//找第一个有xi的那一行,第一个xi不为0的位置            if (B[j][i]){//如果x1刚好换到了第一行没有的位置怎么办啊,那么就不作为!                swap(B[j],B[cnt]);//把当前行换到cnt那一行                break;            }        if (j <n){// 说明一定存在xi            for (j = cnt+1; j < n; j++)//第j行                if (B[j][i])                    for (int k = 0; k <= m; k++)//每一行都减去对应倍的第一行。                        B[j][k] ^= B[cnt][k];//把cnt下面的每一行都和cnt异或            cnt++;        }    }    for (int i = 0; i < n; i++){        if (B[i][m] != 0){//按位或运算更快一些            int t = 0;            for (int j = 0; j < m; j++)                t |= B[i][j];            if (t == 0)                return 0LL;        }    }//还要判断有没有解!!!!!!!    return 1LL<<(m-cnt);//开关的个数才是未知数的个数啊!}






题意:有n个灯,m个开关。每个开关控制对应的灯,问有多少种方案数可以达到想要的开灯效果,初始状态全是关灯。


题解:既然我都知道了是高斯消元……

A开关:1,2

B开关:1,3

三盏灯状态:0 1 1

第一个方程:  x ^ y = 0

第二个方程: x = 1

第三个方程: y = 1



A开关: 1,3

B开关: 2,3,4

C开关: 1,2,4

D开关: 1,3,4

四盏灯状态  ,0111

第一个方程: x1^x3^x4 = 0

第二个方程:x2^x3       = 1

第三个方程:x1^x2^x4 = 1

第四个方程:x2^x3^x4 = 1


把第一个有xi出现的式子换到第i行

然后每一行和这一行异或。

为什么呢?

加法的高斯消元的宗旨是:“消去"某个未知数

比如2x+y=9 x+4y = 10

1式减去两倍的2式就是为了消去未知数x。

而在异或运算中,如果想要消去某个未知数,那就异或上它的本身就好了

比如:消去x1后原方程组变成

x1^x3^x4 = 0

x2^x3 = 1

x2^x3 = 1

x2^x3^x4 = 1

消去x2变成了

x1^x3^x3 = 0

x2^x3 = 1

0

x4 = 1

消去x4之后 原式不变

end

然后算可以知道解的有a个未知数,不知道解的有b个未知数,

也就是说,这b个自由元啊,可以随便开开关关可以是0可以是1,所以解的个数就是2^b。




代码:

#include<bits/stdc++.h>#define SIZE_A 330using namespace std;int luf[SIZE_A][SIZE_A],B[SIZE_A][SIZE_A];int n,m;long long Gauss(){    int cnt = 0;    for (int i = 0; i < m; i++){//每个开关代表的就是未知数,i代表每个多项式前面的系数        int j;        for (j = cnt; j < n; j++)//找第一个有xi的那一行,第一个xi不为0的位置            if (B[j][i]){//如果x1刚好换到了第一行没有的位置怎么办啊,那么就不作为!                swap(B[j],B[cnt]);//把当前行换到cnt那一行                break;            }        if (j <n){// 说明一定存在xi            for (j = cnt+1; j < n; j++)//第j行                if (B[j][i])                    for (int k = 0; k <= m; k++)//每一行都减去对应倍的第一行。                        B[j][k] ^= B[cnt][k];//把cnt下面的每一行都和cnt异或            cnt++;        }    }    for (int i = 0; i < n; i++){        if (B[i][m] != 0){//按位或运算更快一些            int t = 0;            for (int j = 0; j < m; j++)                t |= B[i][j];            if (t == 0)                return 0LL;        }    }//还要判断有没有解!!!!!!!    return 1LL<<(m-cnt);//开关的个数才是未知数的个数啊!}int main(){//freopen("input.txt","r",stdin);    int T;    while (~scanf("%d",&T)){        for (int cas = 1; cas <= T; cas++){            scanf("%d %d",&n,&m);//n盏灯,m个开关            memset(luf,0,sizeof(luf));//全部关上            int k;            for (int i = 0; i < m; i++){                scanf("%d",&k);                while (k--){                    int temp;                    scanf("%d",&temp);//temp代表控制第temp-1那个灯                    luf[temp-1][i] = 1;//m个开关里面的第i个控制了第temp-1那个灯                }            }            int Q;            scanf("%d",&Q);            printf("Case %d:\n",cas);            while (Q--){    for (int i = 0; i < n; i++){        for (int j = 0; j <= m; j++)            B[i][j] = luf[i][j];    }//每进行一次高斯消元,都要把自己的位置改变一次!!注意不要改变原数组                for (int i = 0; i < n; i++){                    int temp;                    scanf("%d",&temp);                    B[i][m] = temp;                }                printf("%I64d\n",Gauss());            }        }    }    return 0;}












这道题是异或之后有多解的方案数,那一个解的在么么哒书上有。

书上说还可以处理方程数和未知数的数量不相等或者解不唯一的情况。还可以求得行列式的值矩阵的秩(我觉得求秩就是方案数)。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 脚不小心扭伤了该怎么办 小鸡脚扭伤了该怎么办 跳高比赛最终成绩相等怎么办 热车1200怠速降不下来怎么办 大腿根骨髓水肿越来越疼怎么办 倒库方向打晚了怎么办 签吻芳颜祛斑液脸脱皮怎么办 3d右边工具栏消失了怎么办 3d菜单栏消失了怎么办 觉得自己性无能不敢谈对象怎么办 护士面试时被问到病人坠床怎么办 三次元仪器坏了怎么办 运动同手同脚怎么办 狗狗突然害怕不敢走路怎么办 一岁半宝宝因为害怕不敢走路怎么办 猫把背拱起来怎么办 穿猫跟鞋走路不稳怎么办 狗狗后腿内八字怎么办 快走后小腿粗了怎么办? 猫的嘴巴烂了怎么办 苹果8丢了已关机怎么办 肚子吃多了难受怎么办 喝水喝的肚子胀怎么办 肚子吃撑了难受怎么办 肚子撑得想吐怎么办 吃饭吃的太饱怎么办 吃饭吃的太撑怎么办 跑步迈不开步子怎么办 踏步走步子反了怎么办 微信不支持计步怎么办 肝癌二次介入后头晕心慌怎么办 跑步跑得胃疼怎么办 如果世界上的猪都死了怎么办 我和我老婆吵架怎么办 我和我老婆吵架了怎么办 智障人士父母死后怎么办 依赖性太强的人怎么办 高考只有一门写准考证号怎么办 ps做动画不流畅怎么办 ff15引擎剑卖了怎么办 fgo从者满了怎么办