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 ...
随机推荐
- hdu 1532(最大流)
Drainage Ditches Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- BZOJ1778 [Usaco2010 Hol]Dotp 驱逐猪猡
首先我们列出转移矩阵$M$,$M_{i, j} = \frac {1 - \frac{p} {q}} {deg[i]}$(i,j之间有边)or $M_{i, j} = 0$(i,j之间没边) 则这个矩 ...
- Android Studio插件推荐(PreIOC,GsonFormat)
好的插件能加快项目的开发速度,尤其是一些针对重复性的代码的插件,所以在这里向大家推荐2款不错的插件,如果以后发现新的好的插件,还会继续推荐,同时欢迎大家推荐 GsonFormat GsonFormat ...
- C++编程优化心得(持续更新)
1. 对齐原则.比如64位总线,每次寻址读取8B.编程时注意变量地址,尽量消耗总线最少的寻址次数.堆内存申请时,系统严格按照对齐原则分配,故而使用时候也尽量不要跨寻址边界. 2. 需要的时候,可为了效 ...
- 网页首页制作总结(div+css+javascript)
一.对网页整体布局,分几个版块 如下图所示: 确定布局之后,规划好网页,准备素材,按照标准文档流的顺序,从上到下,从左到右写入代码. 以上图为例,分为两部分,红色的主体部分和页脚.主体部分分割为头部. ...
- 关于ASP.NET或VS2005 搭建三层架构的理解
最近想学习ASP.NET建网站,关于ASP.NET或VS2005 搭建三层架构的理解,网上摘录了一些资料,对于第(2)点的讲解让我理解印象深刻,如下: (1)为何使用N层架构? 因为每一层都可以在仅仅 ...
- Xcode5 运行程序 提示IOS 模拟器未能安装此应用程序
更新了Xcode5,结果模拟器各种不配合,首先遇到的问题就是提示“IOS 模拟器未能安装此应用程序” 上网查了一下,网友给出的解决办法“删除~/Library/Application Support/ ...
- c/c++面试题(3)strcat/strcmp/strlen/strcpy的实现
1.编写一个函数实现strlen以及strcpy函数. strcpy函数. 后面的字符串拷贝到一个字符数组中,要求拷贝好的字符串在字符数组的首 地址,并且只拷贝到'\0'的位置.原型是 char* m ...
- 团队开发——冲刺2.a
冲刺阶段二(第一天) 1.今天准备做什么? 收集游戏图片:开始.暂停.继续.重新开始.退出……为了界面的后期美工做准备. 2.遇到什么困难? 网上的图片很多,但是比较难找到统一风格的.
- SQLAlchemy一对多总结
1.SQLAlchemy之一对多关系 1.1 创建单表 class Test(Base): __tablename__ = 'user' nid = Colume(Integer,primary_ke ...