【百度之星2019】Strassen

【题目链接】

  http://acm.hdu.edu.cn/showproblem.php?pid=6719

 


在本题中,我们只有两种方法计算两个的矩阵的乘积,第一种为定义法,需要次乘法和次加法。第二种为Strassen分治法,仅当为偶数时可以使用,需要次加法以及再计算次大小为的矩阵的乘积。这次更小矩阵的乘积也可以选择两种方法之一计算。现假设计算机计算一次加法需要单位时间,计算一次乘法需要单位时间,其他任何操作不花费时间,问计算两个的矩阵的乘积至少需要多少时间。输出答案模的余数。

 定义法: A * n * n * (n-1) + B * n * n * n 

Strassen:A * ( n / 2 ) * ( n / 2 ) * ( n - 1 ) +  7 * Min (定义法(n/2),Strassen(n/2))

 

C++

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll mod = 1e9+7;
 5 ll A,B,x;
 6 ll Matrix_Mul( ll n ){
 7     n %= mod ;
 8     ll t1 = B * n % mod * n % mod * n % mod ;
 9     ll t2 = A * n % mod * n % mod * (n-1) % mod ;
10     return ( t1%mod + t2%mod + mod ) % mod ;
11 }
12 
13 ll Strassen( ll n ){
14     if( n&1 )
15         return Matrix_Mul(n);
16 
17     if( n <= 30 * A / (A+B) )
18         return Matrix_Mul(n);
19 
20     ll Half_n = n / 2 ;
21     ll t1 = 18ll * Half_n % mod * Half_n % mod * A % mod ;
22     ll t2 = 7ll * Strassen( Half_n ) % mod ;
23     return ( t1 + t2 + mod ) % mod ;
24 }
25 int main()
26 {
27     ios_base :: sync_with_stdio(false);
28     cin.tie(NULL) , cout.tie(NULL) ;
29 
30     int T;
31     cin >> T ;
32     while( T-- ){
33         cin >> x >> A >> B ;
34         cout << Strassen(x) << endl;
35     }
36     return 0;
37 }
View Code

 

Java

 1 import java.math.* ; 
 2 import java.util.*;
 3 import java.security.MessageDigest;
 4 public class Main{
 5     
 6     static BigInteger Zero = new BigInteger ("0");
 7     static BigInteger One = new BigInteger ("1");
 8     static BigInteger Two = new BigInteger ("2") ;
 9     static BigInteger Four = new BigInteger ("4") ;
10     static BigInteger Seven = new BigInteger ("7");
11     static BigInteger Eighteen = new BigInteger ("18") ;
12     static BigInteger Mod = new BigInteger("1000000007");
13     
14     static  BigInteger Martirx_Mul( BigInteger n , BigInteger a , BigInteger b ){
15         BigInteger Step1 = n.multiply(n).multiply(n).multiply(b) ;
16         BigInteger Step2 = n.subtract(One).multiply(n).multiply(n).multiply(a) ;
17         BigInteger Ans = Step1.add(Step2);
18         return Ans;
19     }
20     
21     static  BigInteger Strassen( BigInteger x , BigInteger a , BigInteger b ){
22         
23         if( x.equals(One) )
24             return Martirx_Mul( One , a , b );
25         
26         BigInteger Half_x = x.divide(Two);
27         BigInteger Step1 = Eighteen.multiply( Half_x ).multiply(Half_x).multiply( a );
28         BigInteger Step2 = Seven.multiply( Strassen( Half_x , a ,b ).min(Martirx_Mul(Half_x,a,b)) ) ;
29         BigInteger Mul = Step1.add(Step2);
30         return Mul.min( Martirx_Mul(x,a,b) );
31     }
32     
33     public static void main( String[] args ){
34         Scanner cin = new Scanner(System.in);
35         int T = cin.nextInt();
36         while( T -- > 0 ){
37             BigInteger a,b,n;
38             
39             n=cin.nextBigInteger();
40             a=cin.nextBigInteger();
41             b=cin.nextBigInteger();
42             BigInteger ans=Strassen(n,a,b).mod(Mod);
43             System.out.println(ans);
44         }
45     }
46     
47 }
View Code

 

转载于:https://www.cnblogs.com/Osea/p/11417088.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值