• HDU 5755 Gambler Bo 2016多校第三场1004


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5755
    题意:给你一个N*M大小的矩阵,在模3域情况下,你可以选矩阵中任意格子使它+2,此时相邻的四个格子会同时+1,让你使用此操作使得整个矩阵每一个地方变为0,输出最小步骤,并且按步骤输出操作的格子。
    题解:高斯消元模板题,不过变成了取模。
       高斯消元解线性方程:http://jingyan.baidu.com/article/39810a23e40c80b636fda63a.html
    那么对于一个模线性方程 a%mod+b%mod+c%mod+....+x%mod=C,如果该方程要求的是a,那么就需要消去其他变量,也就是使得b%mod、c%mod...x%mod变为0。以消去b为例子,关键是要解决假如有另一方程b的系数不为1时,两式相消的情况。那么我们先来考虑一个简单的式子a%mod+b%mod=C,当a、b同时变为原来的两倍也就是2a%mod+2b%mod=D,我们根据式子(a+b)%mod=(a%mod+b%mod)%mod,可以知道D=2C%mod。所以当遇到两个式子同一个变量的系数不相等的时候,只要把两个系数变为相等即可(即求最小公倍数),不过在相乘的时候是怎个式子每一个变量都要乘上相同的倍数,取模结果乘上相同倍数再取模就可以了。详细看代码。
    代码如下:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn=905;
    int T;
    int n,m;
    int equ,var;
    int x[maxn];
    int a[maxn][maxn];
    vector<int>v;
    
    inline int Lcm(int x,int y)
    {
    	return x/__gcd(x,y)*y;
    }
    
    void guass()
    {
    	int sub_r;
    	int r,c;
    	r=c=0;
    	for(;r<equ&&c<var;r++,c++)
    	{
    		sub_r=r;
    		for(int i=r+1;i<equ;i++)//保证需要求的变量在第i行第i列
    			if(abs(a[i][c])>abs(a[sub_r][c]))
    				sub_r=i;
    		if(sub_r!=r)
    			for(int i=0;i<var+1;i++)
    				swap(a[r][i],a[sub_r][i]);
    		if(a[r][c]==0)
    		{
    			r--;
    			continue;
    		}
    		//cout<<a[r][c]<<endl;
    		for(int i=r+1;i<equ;i++)
    		{
    			if(a[i][c])
    			{
    				int lcm=Lcm(abs(a[i][c]),abs(a[r][c]));
    				int tr=lcm/abs(a[r][c]);
    				int ti=lcm/abs(a[i][c]);
    				if(a[r][c]*a[i][c]<0)
    					tr=-tr;
    				for(int j=c;j<var+1;j++)
    				{
    					a[i][j] = ti*a[i][j]-tr*a[r][j];
    					a[i][j] = (a[i][j]%3+3)%3;
    				}
    			}
    		}
    	}
    	for(int i=var-1;i>=0;i--)
    	{
    		int tem=a[i][var];
    		//if(i==var-1)
    		//	cout<<a[i][i]<<" "<<tem<<endl;
    		for(int j=i+1;j<var;j++)
    			if(a[i][j])
    			{
    				tem-=a[i][j]*x[j];
    				tem=(tem%3+3)%3;
    			}
    		x[i]=tem*a[i][i];
    		x[i]%=3;
    
    	}
    }
    
    int main()
    {
    	scanf("%d",&T);
    	while(T--)
    	{
    		memset(x,0,sizeof(x));
    		memset(a,0,sizeof(a));
    		scanf("%d%d",&n,&m);
    		equ=var=m*n;
    		for(int i=0;i<var;i++)
    		{
    			a[i][i]=2;
    			int tr=i/m,tc=i%m;
    			if(tr>0)
    				a[i][i-m]=1;
    			if(tr<n-1)
    				a[i][i+m]=1;
    			if(tc>0)
    				a[i][i-1]=1;
    			if(tc<m-1)
    				a[i][i+1]=1;
    		}
    		int b;
    		for(int i=0;i<n;i++)
    		{
    			for(int j=0;j<m;j++)
    			{
    				scanf("%d",&b);
    				a[i*m+j][var]=(3-b)%3;
    			}
    		}
    		guass();
    		v.clear();
    		for(int i=0;i<var;i++)
    		{
    			//cout<<x[i]<<endl;
    			while(x[i]--)
    				v.push_back(i);
    		}
    		printf("%d\n",v.size());
    		for(int i=0;i<v.size();i++)
    		{
    			int tx=v[i]/m;
    			int ty=v[i]%m;
    			printf("%d %d\n",tx+1,ty+1);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    winform最大化后不遮挡任务栏
    TabControl控件重绘
    EXT gridPanel 添加图片
    好记性不如烂笔头——double
    好记性不如烂笔头——datagridview相关
    datagridview合并相同单元格
    datagridview问题
    Linux折腾记
    TSC打印机使用教程终极版
    在线直播流测试地址
  • 原文地址:https://www.cnblogs.com/zhuyutian/p/5796628.html
Copyright © 2020-2023  润新知