SRM477 Div1 Medium(500) PythTriplets
aとbが互いに素であることから、aとbどちらも偶数になることは無い。また、aもbも奇数と仮定すると、a=2n-1, b=2m-1として、c2=a2+b2=2(2n2+2m2-2n-2m+1)。2(2n2+2m2-2n-2m+1)が平方数であるためには、(2n2+2m2-2n-2m+1)が素因数2を含まなければならいが、(2n2+2m2-2n-2m+1)は奇数。よって、素なピタゴラス数は奇数と偶数の組み合わせ。2部グラフの最大マッチング問題。
#include <iostream> #include <string> #include <vector> #include <cmath> #include <sstream> #include <numeric> using namespace std; class PythTriplets { bool pyth( int a, int b ); int gcd( int a, int b ); int maxmatch2( vector<vector<bool> > edge, int L ); int maxflow( vector<vector<int> > edge, int s=0, int t=-1 ); public: int findMax( vector <string> stick ); }; int PythTriplets::findMax( vector <string> stick ) { stringstream ss( accumulate(stick.begin(), stick.end(),string())); vector<int> s; int temp; while ( ss >> temp ) s.push_back( temp ); int N = (int)s.size(); vector<vector<bool> > E( N, vector<bool>( N, false ) ); vector<int> V; for ( int i=0; i<N; i++ ) if ( s[i] % 2 == 0 ) V.push_back( i ); int L = (int)V.size(); for ( int i=0; i<N; i++ ) if ( s[i] % 2 == 1 ) V.push_back( i ); for ( int i=0; i<L; i++ ) for ( int j=L; j<N; j++ ) E[i][j] = pyth( s[V[i]], s[V[j]] ); return maxmatch2( E, L ); } bool PythTriplets::pyth( int a, int b ) { int c = (int)( sqrt( (long double)( (long long)a*a+(long long)b*b ) ) + 0.01 ); return (long long)a*a+(long long)b*b == (long long)c*c && gcd(a,b) == 1; } int PythTriplets::gcd( int a, int b ) { if ( a < b ) return gcd( b, a ); if ( b == 0 ) return a; return gcd( b, a%b ); } // 2部グラフの最大マッチング // v[:L]が左側、v[L:]が右側 int PythTriplets::maxmatch2( vector<vector<bool> > edge, int L ) { int n = (int)edge.size(); vector<vector<int> > E(n+2,vector<int>(n+2)); for ( int i=0; i<L; i++ ) E[0][i+1] = 1; for ( int i=0; i<L; i++ ) for ( int j=L; j<n; j++ ) if ( edge[i][j] ) E[i+1][j+1] = 1; for ( int i=L; i<n; i++ ) E[i+1][n+1] = 1; return maxflow(E); } // 最大流問題(Edmonds-Karp) int PythTriplets::maxflow( vector<vector<int> > edge, int s, int t ) { int n = (int)edge.size(); if ( t<0 ) t = n-1; int f = 0; vector<vector<int> > F(n,vector<int>(n)); while(true) { vector<int> P(n,-1); P[s]=-2; vector<int> Q(1,s); while ( !Q.empty() && P[t]==-1 ) { int u = Q.back(); Q.pop_back(); for ( int v=0; v<n && P[t]==-1; v++ ) if ( P[v]==-1 && edge[u][v]-F[u][v]>0 ) P[v] = u, Q.push_back(v); } if ( P[t]==-1 ) break; int m = edge[P[t]][t]; for ( int v=P[t]; v!=s; v=P[v] ) m = min(m,edge[P[v]][v]-F[P[v]][v]); f += m; for ( int v=t; v!=s; v=P[v] ) F[P[v]][v] += m, F[v][P[v]] -= m; } return f; }