是2017江苏省赛的第一题,当时在场上没做出来(废话,那个时候又不懂高斯消元怎么写……而且数论也学得一塌糊涂,现在回来补了)

省赛结束之后,题解pdf就出来了,一看题解,嗯……加一行再求逆矩阵从而得到伴随矩阵从而得到答案,emmmmm真是非常通俗易懂呢!

于是在回学校的路上强行回忆上学期学的线性代数,把这题题解的原理想通了,然后到现在把高斯消元法补了,才把这题做出来……

 #include<cstdio>
#include<algorithm>
#define MAXN 205
#define MOD 1000000007
typedef long long ll;
using namespace std;
int n;
ll a[MAXN][*MAXN],det;//注意矩阵的列数要是MAXN的两倍,因为( A , E ) -> ( E , inv(A) )
ll pow(ll a,ll b){//快速幂
ll r=,base=a%MOD;
while(b){
if(b&) r*=base , r%=MOD;
base*=base;
base%=MOD;
b>>=;
}
return r;
}
ll inv_(ll a){return pow(a,MOD-);}//求逆元
void debug()
{
for(int i=;i<=n;i++)
{
for(int j=;j<=*n;j++) printf("%I64d ",a[i][j]);
printf("\n");
}
}
int Gauss_eli(int row,int col)
{
det=;
for(int i=;i<=row;i++)//a[i][i]
{
int tmp;
for(tmp=i;tmp<=n;tmp++) if(a[tmp][i]) break;
if(tmp!=i) det*=-;//行列式交换两行要取负
for(int j=;j<=col;j++) swap(a[tmp][j],a[i][j]);//交换两行
det=(det*a[i][i]%MOD + MOD)%MOD;
ll inv=inv_(a[i][i]);//求得逆元
for(int j=;j<=col;j++) a[i][j]=a[i][j]*inv%MOD;
for(int r=;r<=row;r++)
{
if(r==i) continue;
ll mult=a[r][i];
for(int c=;c<=col;c++) a[r][c]=(a[r][c] - a[i][c]*mult%MOD + MOD)%MOD;//消元
}
//debug(); printf("det = %I64d\n",det);
}
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output1.txt","w",stdout);
while(scanf("%d",&n)!=EOF)
{
for(int j=;j<=n;j++) a[][j]=;
for(int i=;i<=n;i++) for(int j=;j<=n;j++) scanf("%lld",&a[i][j]);
for(int i=;i<=n;i++) for(int j=n+;j<=*n;j++) a[i][j]=(i==(j-n));
Gauss_eli(n,*n);
for(int i=;i<=n;i++)
{
if(i!=) printf(" ");
if(i%==) a[i][n+]=(MOD - a[i][n+])%MOD;
printf("%I64d",(a[i][n+]*det + MOD)%MOD);
}
printf("\n");
}
}

可以说是学到了,对高斯消元、逆元、取模等一系列问题有了更深的认识吧。

关于快速幂:

a^b,把b个a进行两两分组,比如:a*a*a*a*a*a  =>  (a*a)*(a*a)*(a*a)

这样变的好处是,你只需要计算一次a*a,然后将结果(a*a)连乘自己两次就能得到a^6,即(a*a)^3=a^6。算一下发现这次一共乘了3次,少于原来的5次。

核心代码是:

 while(n)
{
if(n&) res=res*a;
n>>=;
a=a*a;
}

完整版是:

 ll fpow(ll a,ll b){//快速幂
ll r=,base=a%MOD;
while(b){
if(b&) r*=base , r%=MOD;
base*=base;
base%=MOD;
b>>=;
}
return r;
}
ll fpow(ll a,ll i){//递归版快速幂
  if (i==) return ;
  int temp=pow(a,i>>);
  temp=temp*temp%MOD;
  if (i&) temp=(ll)temp*a%MOD;
  return temp%MOD;
}

另附一个数据生成器,以后应该经常用得到……

 #include<cstdio>
#include<cstdlib>
#include<ctime>
int get_rand(int m,int n)//[m,n]
{
return( rand()%(n - m + ) + m );
}
int main()
{
freopen("input.txt","w",stdout);
srand(time(NULL));
int n=get_rand(,);
printf("%d\n",n);
for(int i=;i<n;i++)
{
for(int j=;j<=n;j++) printf("%d ",get_rand(,));
printf("\n");
}
}

最新文章

  1. faster-rcnn(testing): ubuntu14.04+caffe+cuda7.5+cudnn5.1.3+opencv3.0+matlabR2014a环境搭建记录
  2. hdu2089 数位dp
  3. Vs注释,vsXML,VSXML注释
  4. PHP vs Python
  5. 如何在Mac下使用TF/SD 卡制作Exynos 4412 u-boot启动盘
  6. POJ 2243 Knight Moves
  7. VS的一部分快捷键
  8. ural 1353. Milliard Vasya&#39;s Function(背包/递归深搜)
  9. JMeter使用简单教程
  10. 实现自己的HashMap
  11. CentOS 安装最新版本 Git
  12. CSS 三角形与圆形
  13. win8 关闭防火墙
  14. scrollTop实现图像循环滚动(实例1)
  15. 不停机不停服务,MYSQL可以这样修改亿级数据表结构
  16. 20145234黄斐《Java程序设计》第十周
  17. Lambada表达式的作用
  18. 【checkbox-group、checkbox】 多项选择器组件说明
  19. does not name a type
  20. [转] 利用dockerize模板为容器内应用生成配置文件和环境变量

热门文章

  1. TIMEOUT HANDLING WITH HTTPCLIENT
  2. 04-vi使用方法详细介绍
  3. MongoDB聚合管道
  4. iOS开发之-- 字符串的操作,去掉某一个字符或者替换成其他字符
  5. hbase shell 启动报错
  6. 解决16bit压缩贴图失真问题
  7. 第二十二篇:基于UDP的一对回射客户/服务器程序
  8. linux shell 随机字符生成单词
  9. Caused by: java.lang.OutOfMemoryError: Failed to allocate a 29433932 byte allocation with 14683576 free bytes and 14MB
  10. postgreSQL连接 java接口