标题:幂一矩阵
天才少年的邻居 atm 最近学习了线性代数相关的理论,他对“矩阵”这个概念特别感兴趣。矩阵中有个概念叫做幂零矩阵。对于一个方阵 M ,如果存在一个正整数 k 满足 M^k = 0 ,那么 M 就是一个幂零矩阵。(^ 表示乘方)
atm 不满足幂零矩阵,他自己设想了一个幂一矩阵:对于一个方阵 M ,如果存在一个正整数 k 满足 M^k = I ,其中 I 是单位矩阵,那么 M 就是一个幂一矩阵。
atm 特别钟情于这样一种方阵:每行每列有且仅有一个 1 。经过 atm 不断实验,他发现这种矩阵都是幂一矩阵。
现在,他的问题是,给定一个满足以上条件的方阵,他想求最小的 k 是多少。
【输入格式】
第一行一个正整数 n ,表示矩阵大小是 n * n 。
接下来 n 行,每行两个正整数 i j 表示方阵的第 i 行第 j 列为 1。
1 <= i, j <= n 。
行号,列号都从1开始。
【输出格式】
一行。一个正整数,即题目中所说最小的 k 。
【样例输入】
5
3 1
1 2
4 4
2 3
5 5
【样例输出】
3
【数据范围】
对于 30% 的数据满足 n <= 10
对于 60% 的数据答案不超过 10^18
对于 100% 的数据满足 n <= 10000
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。
不理解或者需要交流的同学可以粉我新浪微博@雷锹,私信哟!!!
题目所给的矩阵是一种特殊矩阵,掌握矩阵运算的规律就好,这种大数据最好划整为零
今天老师问我这道题用了什么算法,其实没用很高深的算法,只是在掌握运算规律的前提下不断去减少它的运算量
有兴趣的同志可以研究一下我的求最小公倍数部分
这里提醒同志,不要用什么AUP什么特征方程,抓住最简单的矩阵的n次幂运算规则即可
令A:0 1 0
0 0 1
1 0 0
A*A的第一行为一的只有一个,当A的第一行1的位置和第一列一的位置相同
A*A*A为A*A的行乘以A的列
以此类推:所以保存前者的行1的位置和后者的列1的位置
A*A:row(2,3,1) col(3,1,2)
A*A*A:row(3,1,2)col(3,1,2)
另外索引数组用一下,可以把col去掉,想象少了个for循环,很强大的
再者我分别算出每一行的1的位置经过多少次会等于它的行数,求出这些值的最小公倍数OK
package com.jueshai2014;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Scanner;
public class _5 {
@SuppressWarnings("unused")
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int row[] = new int[n + 1];
int pos [] = new int [n + 1];
int count [] = new int [n + 1];
HashSet<Integer> hashset = new HashSet<Integer>();
for (int i = 0; i < n; i++) {
int x = scan.nextInt();
int y = scan.nextInt();
pos[x] = y;
row[x] = y;
}
long time1 = System.currentTimeMillis();
for (int i = 1; i <= n; i++) {
hashset.add(exec(row, pos, i));
}
Iterator<Integer> it= hashset.iterator();
BigInteger sum = new BigInteger(it.next()+"");
while(it.hasNext()){
BigInteger next = new BigInteger(it.next()+"");
BigInteger max,min;
max= sum.max(next);
min = sum.min(next);
for(int i = 1; i <= min.intValue(); i++){
BigInteger temp = new BigInteger(i+"");
if(max.multiply(temp).mod(min).equals(BigInteger.ZERO)){
sum = max.multiply(temp);break;
}
}
}
System.out.println(sum);
long time3 = System.currentTimeMillis();
System.out.println("运行时间:"+ (time3-time1));
}
private static int exec(int[] row, int[] pos, int i) {
int temp = 1;
while (true) {
row[i] = pos[row[i]];
temp++;
if (row[i] == i)
break;
}
if(temp == 2)
return 1;
return temp;
}
}