题意描述:有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消元的更多相关文章

  1. $Gauss$消元

    $Gauss$消元 今天金牌爷来问我一个高消的题目,我才想起来忘了学高消... 高斯消元用于解线性方程组,也就是形如: $\left\{\begin{matrix}a_{11}x_1+a_{12}x_ ...

  2. 求一个n元一次方程的解,Gauss消元

    求一个n元一次方程的解,Gauss消元 const Matrix=require('./Matrix.js') /*Gauss 消元 传入一个矩阵,传出结果 */ function Gauss(mat ...

  3. Gauss 消元(模板)

    /* title:Gauss消元整数解/小数解整数矩阵模板 author:lhk time: 2016.9.11 没学vim的菜鸡自己手打了 */ #include<cstdio> #in ...

  4. hdu 5755(Gauss 消元) &poj 2947

    Gambler Bo Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Tota ...

  5. poj 1681(Gauss 消元)

    Painter's Problem Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5875   Accepted: 2825 ...

  6. POJ 1830 开关问题(Gauss 消元)

    开关问题 Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 7726   Accepted: 3032 Description ...

  7. POJ1830开关问题——gauss消元

    题目链接 分析: 第一个高斯消元题目,操作是异或.奇偶能够用0.1来表示,也就表示成bool类型的方程,操作是异或.和加法没有差别 题目中有两个未知量:每一个开关被按下的次数(0.1).每一个开关的转 ...

  8. Gauss消元模板

    ; //高斯消元模板 //----------------------------------------------------------------------------------- //把 ...

  9. 高斯消元(Gauss消元)

    众所周知,高斯消元可以用来求n元一次方程组的,主要思想就是把一个n*(n+1)的矩阵的对角线消成1,除了第n+1列(用来存放b的)的其他全部元素消成0,是不是听起来有点不可思议??! NO NO NO ...

随机推荐

  1. [hadoop] 一些基础概念

    一.云的概念 1.云计算的概念 随时 随地 使用任何设备 获得任何服务 2.趋势 )资料开始回归集中处理(存储大量资料) 随时存取 降低遗失风险 减少传输成本 促进团队协作 )网页变为预设开发平台(网 ...

  2. 6/13 Sprint2 看板和燃尽图

    部分页面展示

  3. centos 装VBOX

    #cd /etc/yum.repos.d/wget http://download.virtualbox.org/virtualbox/rpm/rhel/virtualbox.repoyum inst ...

  4. JVM实用参数——新生代垃圾回收

    JVM实用参数目录 JVM实用参数——新生代垃圾回收 概述 第1部分  新生代垃圾回收介绍 第2部分 参数介绍 参考 第1部分  新生代垃圾回收介绍 本部分,我们将关注堆(heap) 中一个主要区域, ...

  5. 自己封装的一个java图片验证码

    验证码生成器: package com.lz.Tools; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; ...

  6. hadoop运行原理之Job运行(二) Job提交及初始化

    本篇主要介绍Job从客户端提交到JobTracker及其被初始化的过程. 以WordCount为例,以前的程序都是通过JobClient.runJob()方法来提交Job,但是现在大多用Job.wai ...

  7. register based 和 stack based虚拟机的区别

    其实其核心的差异,就是Dalvik 虚拟机架构是 register-based,与 Sun JDK 的 stack-based 不同,也就是架构上的差异.我先摘录几段网上可以找到的资料,重新整理和排版 ...

  8. enmo_day_03

    安装 装载点 : /u01 (第一个挂载点 LUN1) /u01 (第二个挂载点LUN2) /disk01 目录 : /u01/app/oracle /u01/app/app 文件 : 控制文件 :c ...

  9. 性能测试报告的指标选择、数据选择和分析的参考【以Apache AB test为例】

    前几天尝试用loadrunner初试了一下性能测试,对于如何选择数据.生成数据后如何分析很是迷惑,刚刚翻看一篇网友的博客,很有条理,特此记录一下,以供参考 转自: http://liriguang.i ...

  10. 《C++primer》v5 第2章 变量和基本类型 读书笔记 习题答案

    2.1 int,long long ,short 可表示范围和占用内存空间不同.具体与计算机有关. 无符号类型只能表示0和正数,带符号类型可以表示负数,0,正数. float是单精度,一般占用4个字节 ...