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 ...
随机推荐
- [hadoop] 一些基础概念
一.云的概念 1.云计算的概念 随时 随地 使用任何设备 获得任何服务 2.趋势 )资料开始回归集中处理(存储大量资料) 随时存取 降低遗失风险 减少传输成本 促进团队协作 )网页变为预设开发平台(网 ...
- 6/13 Sprint2 看板和燃尽图
部分页面展示
- centos 装VBOX
#cd /etc/yum.repos.d/wget http://download.virtualbox.org/virtualbox/rpm/rhel/virtualbox.repoyum inst ...
- JVM实用参数——新生代垃圾回收
JVM实用参数目录 JVM实用参数——新生代垃圾回收 概述 第1部分 新生代垃圾回收介绍 第2部分 参数介绍 参考 第1部分 新生代垃圾回收介绍 本部分,我们将关注堆(heap) 中一个主要区域, ...
- 自己封装的一个java图片验证码
验证码生成器: package com.lz.Tools; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; ...
- hadoop运行原理之Job运行(二) Job提交及初始化
本篇主要介绍Job从客户端提交到JobTracker及其被初始化的过程. 以WordCount为例,以前的程序都是通过JobClient.runJob()方法来提交Job,但是现在大多用Job.wai ...
- register based 和 stack based虚拟机的区别
其实其核心的差异,就是Dalvik 虚拟机架构是 register-based,与 Sun JDK 的 stack-based 不同,也就是架构上的差异.我先摘录几段网上可以找到的资料,重新整理和排版 ...
- enmo_day_03
安装 装载点 : /u01 (第一个挂载点 LUN1) /u01 (第二个挂载点LUN2) /disk01 目录 : /u01/app/oracle /u01/app/app 文件 : 控制文件 :c ...
- 性能测试报告的指标选择、数据选择和分析的参考【以Apache AB test为例】
前几天尝试用loadrunner初试了一下性能测试,对于如何选择数据.生成数据后如何分析很是迷惑,刚刚翻看一篇网友的博客,很有条理,特此记录一下,以供参考 转自: http://liriguang.i ...
- 《C++primer》v5 第2章 变量和基本类型 读书笔记 习题答案
2.1 int,long long ,short 可表示范围和占用内存空间不同.具体与计算机有关. 无符号类型只能表示0和正数,带符号类型可以表示负数,0,正数. float是单精度,一般占用4个字节 ...