Project Euler 94

by uwi
@see http://projecteuler.net/index.php?section=problems&id=94
♥0 | Line 53 | Modified 2009-06-23 15:01:29 | MIT License
play

ActionScript3 source code

/**
 * Copyright uwi ( http://wonderfl.net/user/uwi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/fenJ
 */

package {
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.utils.getTimer;
    // @see http://projecteuler.net/index.php?section=problems&id=94
    public class Euler94 extends Sprite {
        private var _tf : TextField;
  
        public function Euler94() {
            _tf = new TextField();
            _tf.width = 465;
            _tf.height = 465;
            addChild(_tf);
            
            var s : int = getTimer();
            _tf.appendText(solve().toString() + "\n");
            var g : int = getTimer();
            _tf.appendText((g - s).toString() + " ms\n");
        }
        
        private const N : int = 1000000000;
        
        // 3辺の長さをa,a,cとする。(c = a+1 or a-1)
        // 面積はS=c√(4a^2-c^2)/4
        // 周の長さはL=2a+c
        // Sの√内が平方数でないといけなく、4a^2=(2a)^2より、ピタゴラス数を生成して該当するa,cを求める。
        // m,n,k(どれも自然数、m>n, m,nは互いに素)に対して、
        // 2a = k(m^2 + n^2)=ka'
        // c = k(2mn) or k(m^2 - n^2) = kc'
        // cはa±1なので、aとcは互いに素。よって2aとcの最大公約数はたかだか2
        // m^2+n^2は奇数なので、k=1ではない。よってk=2
        // b'=√(a'^2-c'^2)=(m^2-n^2 or 2mn) とすると、
        // S=c'b', L=2(a'+c')
        //
        // あとはa'と2c'の差が1となるような(m,n)の組を列挙してLを加算していけばよい。
        // mを固定するとa'-2c'=±1の解は4個。そのうち2個は整数になり得ないので、m 1あたりたかだか2個のnについて調べればよい。
        private function solve() : int
        {
            var sum : int = 0;
            
            // 2(m^2+n^2)+(m^2+n^2)±1 <= N
            var mlim : int = Math.sqrt((N - 1) / 3); 
            for(var m : int = 1;m <= mlim;m++){
                var ncans : Object = {};
                var ncan : Number;
                ncan = 2 * m - Math.sqrt(3 * m * m + 1); if(ncan == ncan >> 0)ncans[ncan] = ncan;
//                ncan = 2 * m - Math.sqrt(3 * m * m - 1); if(ncan == ncan >> 0)ncans[ncan] = ncan;
//                ncan = Math.sqrt((m * m + 1) / 3); if(ncan == ncan >> 0)ncans[ncan] = ncan;
                ncan = Math.sqrt((m * m - 1) / 3); if(ncan == ncan >> 0)ncans[ncan] = ncan;
                
                for each(var n : int in ncans){
                    if(n <= 0)continue;
                    if(((m ^ n) & 1) == 0 || GCD(m, n) != 1)continue;
                    var a : int = m * m + n * n;
                    var ch1 : int = 2 * m * n;
                    var ch2 : int = m * m - n * n;
                    var p : int;
                    if(2 * ch1 + 1 == a || 2 * ch1 - 1 == a){
                        _tf.appendText(m.toString() + "\t" + n.toString() + "\n");
//                        _tf.appendText((ch1 * ch2).toString() + "\n");
                        p = 2 * (a + ch1);
                        if(p < N)sum += p;
                    }
                    if(2 * ch2 + 1 == a || 2 * ch2 - 1 == a){
                        _tf.appendText(m.toString() + "\t" + n.toString() + "\n");
//                        _tf.appendText((ch1 * ch2).toString() + "\n");
                        p = 2 * (a + ch2);
                        if(p < N)sum += p;
                    }
                }
            }
            return sum;
        }
        
        private static function GCD(a : int, b : int) : int
        {
            return b == 0 ? a : GCD(b, a % b);
        }
    }
}