0w1

CFR 707 C. Pythagorean Triples ( Math )

Problem - C - Codeforces
網路上找到了這張圖。以前學過這個定理。
f:id:h0rnet:20160821031053p:plain
滿足畢氏定理 a^2 + b^2 = c^2 的 a, b, c 必然滿足且各自唯一對應到
a = 2 * m * n, b = m^2 - n^2, c = m^2 + n^2
整數解 ( a, b, c ) 必然滿足一組整數的 ( m, n ) 且 m ≥ n ( 為什麼呢,還沒想到 )
因此用根號的複雜度就能完成枚舉了。
但我還是 WA 了,因為沒有仔細判斷不小心得出解為 0 的情況。

void solve(){
    int N; cin >> N;
    int s = sqrt( N );
    for( int i = 1; i <= s; ++i ){
        int n2 = N - i * i;
        if( sqrt( n2 ) * sqrt( n2 ) == n2 ){
            ll m = n2, n = i;
            if( not ( m > n ) ) swap( m, n );
            if( m == 0 or n == 0 ) continue;
            ll ans1 = 1LL * m * m - 1LL * n * n;
            ll ans2 = 2LL * m * n;
            if( ans1 == 0 or ans2 == 0 ) continue;
            if( ans1 * ans1 + ans2 * ans2 != 1LL * N * N ) continue;
            cout << ans1 << " " << ans2 << endl;
            return;
        }
    }
    for( int i = 1; i <= s; ++i ){
        if( N % i == 0 ){
            ll m_n = i;
            ll mpn = N / i;
            ll m = ( m_n + mpn ) / 2;
            ll n = ( mpn - m_n ) / 2;
            m = abs( m ), n = abs( n );
            if( not ( m > n ) ) swap( m, n );
            if( m_n != m - n or mpn != m + n ) continue;
            if( m == 0 or n == 0 ) continue;
            ll ans1 = m * m + n * n;
            ll ans2 = 2 * m * n;
            if( ans1 == 0 or ans2 == 0 ) continue;
            if( 1LL * N * N + ans2 * ans2 != ans1 * ans1 ) continue;
            cout << ans1 << " " << ans2 << endl;
            return;
        }
    }
    if( N % 2 == 0 ){
        N /= 2;
        int sn = sqrt( N );
        for( int i = 1; i <= sn; ++i )
            if( N % i == 0 ){
                ll m = i, n = N / i;
                if( not ( m > n ) ) swap( m, n );
                if( m == 0 or n == 0 ) continue;
                ll ans1 = m * m - n * n;
                ll ans2 = m * m + n * n;
                N *= 2;
                if( ans1 == 0 or ans2 == 0 ) continue;
                if( ans1 * ans1 + 1LL * N * N != ans2 * ans2 ) continue;
                cout << ans1 << " " << ans2 << endl;
                return;
            }
    }
    cout << -1 << endl;
}