結果
| 問題 |
No.2447 行列累乗根
|
| コンテスト | |
| ユーザー |
👑 |
| 提出日時 | 2023-04-08 08:17:52 |
| 言語 | C++17(gcc12) (gcc 12.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 5,038 bytes |
| コンパイル時間 | 10,795 ms |
| コンパイル使用メモリ | 276,860 KB |
| 最終ジャッジ日時 | 2025-02-12 03:48:37 |
|
ジャッジサーバーID (参考情報) |
judge2 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 23 WA * 5 |
ソースコード
// 誤解法(厳密に0である値の近似誤差を無視した解法)チェック
#pragma GCC optimize ( "O3" )
#pragma GCC optimize( "unroll-loops" )
#pragma GCC target ( "sse4.2,fma,avx2,popcnt,lzcnt,bmi2" )
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define MAIN main
#define TYPE_OF( VAR ) remove_const<remove_reference<decltype( VAR )>::type >::type
#define UNTIE ios_base::sync_with_stdio( false ); cin.tie( nullptr )
#define CEXPR( LL , BOUND , VALUE ) constexpr LL BOUND = VALUE
#define CIN( LL , A ) LL A; cin >> A
#define ASSERT( A , MIN , MAX ) assert( ( MIN ) <= A && A <= ( MAX ) )
#define CIN_ASSERT( A , MIN , MAX ) CIN( TYPE_OF( MAX ) , A ); ASSERT( A , MIN , MAX )
#define FOR( VAR , INITIAL , FINAL_PLUS_ONE ) for( TYPE_OF( FINAL_PLUS_ONE ) VAR = INITIAL ; VAR < FINAL_PLUS_ONE ; VAR ++ )
#define REPEAT( HOW_MANY_TIMES ) FOR( VARIABLE_FOR_REPEAT , 0 , HOW_MANY_TIMES )
#define QUIT return 0
#define COUT( ANSWER ) cout << ( ANSWER ) << "\n"
#define SET_PRECISION( PRECISION ) cout << fixed << setprecision( PRECISION )
template <typename T>
class TwoByTwoMatrix
{
public:
T m_M00;
T m_M01;
T m_M10;
T m_M11;
public:
inline TwoByTwoMatrix( const T& M00 , const T& M01 , const T& M10 , const T& M11 ) noexcept;
TwoByTwoMatrix<T>& operator=( const TwoByTwoMatrix<T>& mat ) noexcept;
inline TwoByTwoMatrix<T> operator*( const TwoByTwoMatrix<T>& mat );
};
template <typename T> inline TwoByTwoMatrix<T>::TwoByTwoMatrix( const T& M00 , const T& M01 , const T& M10 , const T& M11 ) noexcept : m_M00( M00 ) , m_M01( M01 ) , m_M10( M10 ) , m_M11( M11 ) {}
template <typename T>
TwoByTwoMatrix<T>& TwoByTwoMatrix<T>::operator=( const TwoByTwoMatrix<T>& mat ) noexcept
{
if( &mat != this ){
m_M00 = mat.m_M00;
m_M01 = mat.m_M01;
m_M10 = mat.m_M10;
m_M11 = mat.m_M11;
}
return *this;
}
template <typename T> inline TwoByTwoMatrix<T> TwoByTwoMatrix<T>::operator*( const TwoByTwoMatrix<T>& mat ) { return TwoByTwoMatrix<T>( m_M00 * mat.m_M00 + m_M01 * mat.m_M10 , m_M00 * mat.m_M01 + m_M01 * mat.m_M11 , m_M10 * mat.m_M00 + m_M11 * mat.m_M10 , m_M10 * mat.m_M01 + m_M11 * mat.m_M11 ); }
void stod( const string& s , ll& num , double& answer )
{
bool negative;
uint i_start;
if( s.substr( 0 , 1 ) == "-" ){
negative = true;
i_start = 1;
} else {
negative = false;
i_start = 0;
}
uint size = s.size();
uint exponent = 0;
num = 0;
FOR( i , i_start , size ){
string c = s.substr( i , 1 );
if( c == "." ){
assert( exponent == 0 );
assert( i - i_start == 1 );
exponent = size - 1 - i;
assert( exponent <= 5 );
} else {
num = num * 10 + stoi( c );
}
}
answer = ( negative ? - num : num );
while( exponent != 0 ){
answer *= 0.1;
exponent--;
}
return;
}
int MAIN()
{
UNTIE;
SET_PRECISION( 5 );
double M_entry[2][2];
double ( &M0 )[2] = M_entry[0];
double ( &M1 )[2] = M_entry[1];
double& M00 = M0[0];
double& M01 = M0[1];
double& M10 = M1[0];
double& M11 = M1[1];
ll num[2][2];
double e[2];
double& e0 = e[0];
double& e1 = e[1];
double U_entry[2][2];
double ( &U0 )[2] = U_entry[0];
double ( &U1 )[2] = U_entry[1];
double& U00 = U0[0];
double& U01 = U0[1];
double& U10 = U1[0];
double& U11 = U1[1];
double norm[2];
double& norm0 = norm[0];
double& norm1 = norm[1];
CEXPR( int , bound_T , 100000 );
CIN_ASSERT( T , 1 , bound_T );
REPEAT( T ){
FOR( i , 0 , 2 ){
double ( &Mi )[2] = M_entry[i];
ll ( &numi )[2] = num[i];
FOR( j , 0 , 2 ){
CIN( string, S );
stod( S , numi[j] , Mi[j] );
}
}
double tr = M00 + M11;
double det = M00 * M11 - M01 * M10;
double disc = tr * tr - 4.0 * det;
double discrt = sqrt( disc ); // ここで0とのズレが生じうる
e[0] = ( tr + discrt ) / 2.0;
e[1] = ( tr - discrt ) / 2.0;
double normsq;
bool degenerate = false;
FOR( j , 0 , 2 ){
double& ej = e[j];
double& U0j = U0[j];
double& U1j = U1[j];
double& normj = norm[j];
U0j = M10;
U1j = ej - M00;
normsq = U0j * U0j + U1j * U1j;
normj = sqrt( normsq ); // ここで0とのズレが生じうる
if( normj == 0.0 ){
U0j = ej - M11;
U1j = M01;
normsq = U0j * U0j + U1j * U1j;
normj = sqrt( normsq ); // ここで0とのズレが生じうる
if( normj == 0.0 ){
degenerate = true;
break;
}
}
}
if( degenerate ){
e0 = M11;
e1 = M11;
U00 = 1.0;
U10 = 0.0;
U01 = 0.0;
U11 = 1.0;
} else {
U00 /= norm0;
U10 /= norm0;
U01 /= norm1;
U11 /= norm1;
}
TwoByTwoMatrix<double> U{ U00 , U01 , U10 , U11 };
TwoByTwoMatrix<double> Uinv{ U00 , U10 , U01 , U11 };
TwoByTwoMatrix<double> Dcbrt{ cbrt( e0 ) , 0.0 , 0.0 , cbrt( e1 ) };
TwoByTwoMatrix<double> Mcbrt = U * Dcbrt * Uinv;
cout << Mcbrt.m_M00 << " " << Mcbrt.m_M01 << "\n";
cout << Mcbrt.m_M10 << " " << Mcbrt.m_M11 << "\n";
}
QUIT;
}