gauss消元
题意描述:有n个星球,m台望远镜。每台望远镜有一个开始时间和结束时间,但只给出了月、日的信息,没有给出年份,每台望远镜记录了它所观测的星球上发生的各类事件的次数。每类事件持续的时间是恒定的,且不会超过365天,不管在哪个星球上发生。告诉你每台望远镜的起止时间,和它观测到的各类时间发生的次数。问每类事件持续多长时间?可能有多个解,输出一个可行解即可。
数据范围:n<200,m<200
分析:设第i类时间持续的时间为xi,第i个望远镜的观测时间长度为Ci,它观测到的各类事件发生的次数为fi,则第i个望远镜可以列出以下方程:
∑fi*xi%365=Ci
于是可以得到一个模线性方程组。但是因为365不是质数,不能直接利用高斯-亚当消元法解这个方程组。为什么呢?
因为高斯亚当消元要对方程进行线性变换,比如乘上某个系数。但是乘的系数与模不互质的话,则变换前后两个方程不是等价的,可能造成解集扩大。
比如方程A:2x%15=1
方程A乘上系数3,得到方程B: 6x%15=3。
方程A和B不是等价的。满足A的解一定满足B,但是满足B的解不一定满足A。或者说方程A可以得到B,但方程B不能得到A。
所以对模型线性方程组要进行线性变换一定要保证模是质数。
那么接下来怎么做呢?对365进行质因数分解:365=73*5.
于是由方程∑fi*xi%365=Ci可以得到两个方程:
∑fi*xi%73=Ci%73
∑fi*xi%5=Ci%5
于是原来的方程组可以化成两个方程组。对其分别求解,设方程1的解集为X1,方程2的解集为X2。
则可以由X1和X2构造出一个解X,同时满足两个方程,即利用中国剩余定理.
代码如下:
/*
Sluzbeno rjesenje zadatka Planete. Trebalo bi dobiti 100% bodova.
Slozenost algoritma: O( N^2*F )
Autor: Goran Zuzic
*/ #include <algorithm>
#include <functional> #include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring> #include <vector>
#include <string> using namespace std; const int MAXN = 210;
const int MAXF = 210; int N, F;
int DuM[ 12 ] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int Init[ MAXN ][ MAXF+1 ];
int Mat[ MAXN ][ MAXF+1 ]; inline int get_day()
{
int d, m; scanf( "%d %d", &d, &m ); --d, --m; for( int i = 0; i < m; ++i )
d += DuM[i]; return d;
} int Sol5[ MAXF ];
int Sol73[ MAXF ]; int Inverz[ 100 ];
int superOk = true; void gauss_solve( int p, int *Sol )
{
for( int i = 0; i < N; ++i )
for( int j = 0; j <= F; ++j )
Mat[i][j] = Init[i][j] % p;
Inverz[0] = 0;
for( int i = 1; i < p; ++i )
for( int j = 1; j < p; ++j )
if( (i*j)%p == 1 )
Inverz[i] = j;
int R = 0;
for( int s = 0; s < F; ++s ) {
int indeks = -1;
for( int i = R; indeks == -1 && i < N; ++i )
if( Mat[i][s] != 0 )
indeks = i; //indeks是该列不为0的所有行的第一行
if( indeks == -1 ) continue;//该列为0
if( R != indeks )//第R行和第i行交换
for( int i = 0; i <= F; ++i )
swap( Mat[R][i], Mat[indeks][i] );
int mnozi = Inverz[ Mat[R][s] ];//求系数的逆元,作为倍数。
for( int i = 0; i <= F; ++i )
Mat[R][i] = ( Mat[R][i]*mnozi ) % p;
for( int i = 0; i < N; ++i )
if( i != R ) {
int coef = Mat[i][s];
for( int j = 0; j <= F; ++j ) {
Mat[i][j] -= coef * Mat[R][j];
Mat[i][j] %= p; if( Mat[i][j] < 0 ) Mat[i][j] += p;
}
}
++R;
}
for( int i = 0; i < N; ++i ) {
int first = -1;
for( int j = 0; j < F; ++j )
if( Mat[i][j] != 0 ) {
first = j;
break;
} if( first == -1 ) {
if( Mat[i][F] != 0 ) { superOk = false; return ; }
continue;
}
Sol[ first ] = Mat[i][F];
}
} int main( void )
{
scanf( "%d %d", &N, &F );
for( int i = 0; i < N; ++i ) {
int a = get_day();
int b = get_day();
for( int j = 0; j < F; ++j )
scanf( "%d", Init[i] + j );
Init[i][F] = ((b-a)%365+365)%365;
} gauss_solve( 5, Sol5 );
gauss_solve( 73, Sol73 ); if( !superOk ) { printf( "-1\n" ); return 0; } for( int i = 0; i < F; ++i ) {
int tmp = ( 146*Sol5[i] + 220*Sol73[i] ) % 365;
if( tmp == 0 ) tmp = 365;
printf( "%d\n", tmp );
}
return 0;
}
gauss消元的更多相关文章
- $Gauss$消元
$Gauss$消元 今天金牌爷来问我一个高消的题目,我才想起来忘了学高消... 高斯消元用于解线性方程组,也就是形如: $\left\{\begin{matrix}a_{11}x_1+a_{12}x_ ...
- 求一个n元一次方程的解,Gauss消元
求一个n元一次方程的解,Gauss消元 const Matrix=require('./Matrix.js') /*Gauss 消元 传入一个矩阵,传出结果 */ function Gauss(mat ...
- Gauss 消元(模板)
/* title:Gauss消元整数解/小数解整数矩阵模板 author:lhk time: 2016.9.11 没学vim的菜鸡自己手打了 */ #include<cstdio> #in ...
- hdu 5755(Gauss 消元) &poj 2947
Gambler Bo Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Tota ...
- poj 1681(Gauss 消元)
Painter's Problem Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 5875 Accepted: 2825 ...
- POJ 1830 开关问题(Gauss 消元)
开关问题 Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 7726 Accepted: 3032 Description ...
- POJ1830开关问题——gauss消元
题目链接 分析: 第一个高斯消元题目,操作是异或.奇偶能够用0.1来表示,也就表示成bool类型的方程,操作是异或.和加法没有差别 题目中有两个未知量:每一个开关被按下的次数(0.1).每一个开关的转 ...
- Gauss消元模板
; //高斯消元模板 //----------------------------------------------------------------------------------- //把 ...
- 高斯消元(Gauss消元)
众所周知,高斯消元可以用来求n元一次方程组的,主要思想就是把一个n*(n+1)的矩阵的对角线消成1,除了第n+1列(用来存放b的)的其他全部元素消成0,是不是听起来有点不可思议??! NO NO NO ...
随机推荐
- javascript的一些基础
当复制的两个变量的地址不同时他们是不相等的如下代码所示 function getFunction(value){ return function(value){ return value; } } v ...
- C#窗体自定义控件
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; u ...
- 如何获取有性能问题的SQL
1.通过用户反馈获取存在性能问题的SQL. 2.通过慢查日志获取存在性能的SQL. 启动慢查日志 slow_query_log=on set global slow_query_log=o ...
- [转]CSS,font-family,常用网页字体
http://www.zreading.cn/ican/2014/10/css-font-family/ CSS,font-family,好看常用的中文字体 2014-10-14 例1(小米米官网): ...
- Android在Service中显示Dialog
在Service中弹出一个Dialog对话框 第1步:在应用的AndroidManifest.xml中需要添加权限.没有无法显示. <uses-permission android:name=& ...
- IEnumerable接口的Aggregate方法
以前小猪为了累加一个集合中的类容通常会写出类似这样的C#代码: string result ="": foreach (var item in items) { result+=i ...
- mysql 中execute、executeQuery和executeUpdate之间的区别
在用纯JSP做一个页面报警功能的时候习惯性的用executeQuery来执行SQL语句,结果执行update时就遇到问题,语句能执行,但返回结果出现问题,另外还忽略了executeUpdate的返回值 ...
- 关于mysql jsp字符编码的问题解决
1.对于post表单的jsp界面,要采用与数据库统一字符编码,在页头设置 <%@ page language="java" import="java.util.*& ...
- IOS开发支付宝集成思路
一般情况下支付功能的交互流程 比如我们去某个APP去支付一个产品,流程为:1.用户点击支付->2.客户端请求服务器用户支付->3.服务器接收请求生成金额订单等要给第三方支付的一切信息,并生 ...
- JS三元
((productDatas[i].Img.indexOf("http") == -1) ? ("/upload/190-160/" + productData ...