CODYコンテスト2020プロジェクトオイラーI10の質問

問題230。プロジェクトオイラー:問題1、3と5の倍数

3または5の倍数である10未満のすべての自然数をリストすると、3、5、6、および9が得られます。これらの倍数の合計は23です。

入力値の下の3または5のすべての倍数の合計を見つけます。

プロジェクトオイラー問題1に感謝します 

入力値より下のすべての自然数と、3または5の倍数の合計を返します。

この質問には時間ベクトル法を使用しました。入力値xより下のすべての自然数(1〜x1)はベクトルに格納され、ベクトルの3つの剰余(mod)と5つの剰余が0であるかどうか、および3の余りが合計されます。5を超える結果はOR(||の代わりに|)演算であるため、マスクベクトルが取得され、0は3または5の倍数に対応し、1は3または5の倍数に対応します。次に、インデックスx 3または5の倍数である自然数を取得し、合計します。

function y = euler001(x)
    x=1:x-1;
    y =sum(x(mod(x,3)==0 | mod(x,5)==0));
end

問題232.プロジェクトオイラー:問題2、フィボナッチの合計

フィボナッチ数列の新しい各項は、前の2つの項を追加することによって生成されます。1と2から始めると、最初の10の用語は次のようになります。

1、2、3、5、8、13、21、34、55、89、..。

値が入力値を超えないフィボナッチ数列の項を検討することにより、偶数値の項の合計を求めます。

1 2から始まるフィボナッチ数列が与えられた場合、入力値を超えず、偶数である値の合計を見つけます。

長い間考えた結果、一般的な項の数式を使用したり、数式を満たす偶数値の合計を使用したりするなど、効果的な方法は見つかりませんでした。唯一の便利な点は、偶数値の項の分布が特定の法則を満たしていることを見つけることです。 :2の添え字は2、8の添え字は5、34は8などです。3i+ 2項目は偶数であり、iは0より大きい整数であると推測できます。 Fibonacciシーケンスを作成すると、現在の添え字を3で割った値が2であるかどうかが判断されます。2の場合、結果に値を追加します。もちろん、現在の値が入力より大きいかどうかを判断するために追加し、次の場合は停止します。それは大きいです。スペースを節約するために、ストレージに配列を使用する代わりに、3つの変数a1、a2、a3を使用することで実現できます。毎回a3 = a1 + a2を計算して判断した後、a1 = a2; a2 = a3を更新します。

function y = euler002(x)
    a1=1;
    a2=2;
    i=3;
    y=2;
    while true
        a3=a1+a2;
        if a3>x
            break
        end
        if mod(i,3)==2
            y=y+a3;
        end
        i=i+1;
        
        a1=a2;
        a2=a3;
    end
end

問題234.プロジェクトオイラー:問題3、最大の素因数

13195の素因数は5、7、13、29です。

入力される数の最大の素数は何ですか?入力は大きな数の場合はuint64である可能性があり、outは倍精度でなければなりませんか?

プロジェクトオイラー問題3に感謝します 

入力値は、最大の素数見つけるための複数の素数の積と見なすことができます(最初は最大の因子として実行されました...)

最初の方法であるmatlabは、n以下の素数の配列を直接生成し、入力値xについて、素数データprimes(x / 2)を取得し、xを逆の順序で除算できるかどうかを判断します。最後の桁、そしてそれが満たされている場合、彼は最大の素数ですが、最初の例では、matlab:pawnです。

次の例は大きいため、最適化する必要があります。同時に、matlabは入力値が素数であるかどうかを判断するためのisprimeも提供します。これは非常に便利です。したがって、2番目の方法は、x / 2から前方にトラバースして、現在の値が分割可能なxを満たし、同時に素数であるかどうかを判断することです。

k=floor(x/2);
while true
    if mod(x,k)==0 && isprime(k)
        y=k;
        break
    end
end

しかし、それは非常に時間がかかります。

短い除算で解くことができます。まず、xについて、2で除算できないまで2で除算し続け、次の素数まで3、5、7、11などで除算し続けます。が除数として使用され、素数の2乗がxより大きい。、現在のxが素数であり、他の素数の積に分解できないことを示します(証明:被除数がiであると仮定すると、電流はxであり、前の累積によれば、xの因数にはi未満のすべての素数が含まれていないため、xの最小値はiである可能性があり、それでも均等に除算できるかどうかを判断する必要があります。 xの最小の因数がiの場合、残りの因数の積はx / iですが、i ^ 2> xの場合、x / iはi未満になり、「xの因数にはすべての素数が含まれるわけではありません。 iよりも小さい "相互に排他的。現在の状況は割り切れるだけです。割り切れない場合は、次の素数にジャンプし、大きくなり、x / iが小さくなります。したがって、それは真実ではありません。 i ^ 2> x、xは他の素数の積に分解できません)

function y = euler003(x)
    i=1;
    while true
       while ~isprime(i)
           i=i+1;
       end
       %找到下一个的质数
       if(i^2>=x)
           y=x;
           return;
       end
       %如果质数的平方大于当前数,说明x已经不能再分解为质数的乘积
       while mod(x,i)==0
           x=x/i;
       end
       %累除
       i=i+1;
    end
end

問題235。プロジェクトオイラー:問題4、回文数

回文数は、両方の方法で同じように読み取られます。2つの2桁の数字の積から作られた最大の回文は9009 = 9199です。

入力された数以下の数の積から作られた最大の回文を見つけます。

プロジェクトオイラー問題4に感謝します 

回文の定義はあまりにも馴染みがあります。2つの2桁の数字の積の最大回文は9009(91 * 99)です。入力された数字の積以下の最大の回文を見つけます。

かなりばかげているので、回文数などの数学的特性の一部を使用せず、入力xよりも小さい2つの数のすべての積を大きいものから小さいものに直接並べ替えて、それが回文であるかどうかを判断します。ターン(古い暴力)

function y = euler004(x)
    n=(x:-1:1)'*(x:-1:1);
    n=sort(n(:),'descend');
    for i=1:length(n)
        ret=1;
        s=char(num2str(n(i)));
        for k=1:length(s)/2
            if s(k)~=s(end-k+1)
                ret=0;
                break
            end
        end
        if(ret)
            y=n(i);
            break;
        end
    end
end

問題239。プロジェクトオイラー:問題5、最小公倍数

2520は、余りなしで1から10までの各数値で除算できる最小の数値です。

1から入力数までのすべての数で均等に割り切れる最小の正の数は何ですか?

プロジェクトオイラー問題5に感謝します 

2520は、1から10までの最小公倍数です。1からxまでの最小公倍数を見つけます。Matlabは、最小公倍数lcmを提供します。ただし、2つの数値または2つのベクトルの最小公倍数のみがサポートされ、複数の数値の最小公倍数はサポートされませんが、1〜xをsym形式に変換することで操作できます。

function y = euler005(x)
  y=lcm(sym(1:x));
  y=double(y);
end

私のマシンでログを実行することに問題がありますが、送信後にdouble形式に対応する記号がないため、直接トラバースされ、毎回、前の最小公倍数yと現在の数の最小公倍数が計算されます。

function y = euler005(x)
    y=1;
    for i=2:x
        y=lcm(i,y);
    end
end

私はもう武道について話しません。

第六题問題240。プロジェクトオイラー:問題6、自然数、平方、合計。

最初の10個の自然数の2乗の合計は、

1 ^ 2 + 2 ^ 2 + ... + 10 ^ 2 = 385最初の10個の自然数の合計の2乗は次のとおりです。

(1 + 2 + ... + 10)^ 2 = 55 ^ 2 = 3025したがって、最初の10個の自然数の2乗の合計と合計の2乗の差は3025-385 = 2640です。

最初のN(Nは入力)の自然数の2乗の合計と合計の2乗の差を求めます。

プロジェクトオイラー問題6に感謝します 

1からNの合計の2乗と1からNの2乗の合計の差を計算します。

最初の方法は、1からxまでのベクトルをリストし、それぞれベクトルの合計を見つけて、ベクトル点の合計と正方形の差を2乗することです。

x=20;
x=1:x;
y=sum(x)^2-sum(x.^2);

コメントエリアの誰かがLOOPはクールではないと言った

さて、1からxの合計は、合計式x(x + 1)/ 2で合計できます。1、2 ^ 2、3 ^ 2、...、n ^ 2の合計はx(x + 1)です。 )(2x + 1)/ 6、前者から後者を引いた2乗は、最終的にx(x ^ 2-1)(3n + 2)/ 12に縮小されます。

など:

function y = euler006(x)
  y = x*(x^2-1)*(3*x+2)/12;
end

問題241.プロジェクトオイラー:問題7、N番目の素数

最初の6つの素数(2、3、5、7、11、および13)をリストすると、6番目の素数が13であることがわかります。

N番目の素数は何ですか?

プロジェクトオイラー問題7に感謝します 

2から始まるn番目の素数を返します。素数などのいくつかのプロパティに依存しない場合は、トラバーサルのみがあります。

function y = euler007(x)
    j=0;
    i=2;
    while true
        if isprime(i)
            j=j+1;
        end
        if(j==x)
            y=i;
       
            break;
        end
        i=i+1;
    end
end

第八题問題246。プロジェクトオイラー:問題8、大きな数字の文字列から最大の積を見つける

n桁の数字で5桁連続の最大の積を見つけます。

7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843 8586156078911294949545950173795833195285320880551112540698747158523863050715693290963295227443043557 6689664895044524452316173185640309871112172238311362229893423380308135336276614282806444486645238749 3035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776 6572733300105336788122023542180975125454059475224352584907711670556013604839586446706324415722155397 5369781797784617406495514929086256932197846862248283972241375657056057490261407972968652414535100474 8216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586 17866458359124566529476545682848912883142607690042242190226710556263211111093705442175069416589604080719840385096245544436298123098787992724428490918884580156166097919133875499200524063689912560717606 0588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450

大きな数字は文字列、1xn文字として与えられます。

プロジェクトオイラー問題8に感謝します 

指定された数の文字列(たとえば、上記の数の場合は文字列を使用して格納します)で、5つの連続する数値の最大の積を見つけます。直接トラバースすることも、5つの連続したスライディングウィンドウと見なすこともできます。最初の8ビットがabcdefghであるとすると、最初の計算はa * b * c * d * eであり、ステップサイズは1b * c * d *です。 e * f b * c * d * eが計算されているため、fがaより大きい場合、b * c * d * e * fの値はa * b * c * d * eより大きいので、スライドします。左に1ユニット、それ以外の場合は、ステップ長2のa * bとf * gのサイズを引き続き比較します。後者の方が大きい場合は、2ユニットを直接スライドさせます。ステップ長が4の場合。 5ユニットを直接右にスライドさせます。他の方法も解決できます。

境界の問題を判断するのは面倒なので、入力文字列の長さを取得した後、文字列の後に4つのゼロが追加されます。

function y = euler008(x)
     n=length(x);
     x(end+1:end+4)='0000';
     y=-Inf;
     i=1;
     while i<=n-4
         temp=double(x(i:i+4))-48;
         y=max(y,prod(temp));
         if (i==n-4)
             break;
         end
         if temp(1)<=double(x(i+5))-48
             i=i+1;
         elseif temp(1)*temp(2)<=(double(x(i+5))-48)*(double(x(i+6))-48)
            i=i+2;
         elseif temp(1)*temp(2)*temp(3)<=(double(x(i+5))-48)*(double(x(i+6))-48)*(double(x(i+7))-48)
             i=i+3;
         elseif temp(1)*temp(2)*temp(3)*temp(4)<=(double(x(i+5))-48)*(double(x(i+6))-48)*(double(x(i+7))-48)*(double(x(i+8))-48)
             i=i+4;
         else
             i=i+5;
         end
     end
end

問題249。プロジェクトオイラー:問題9、ピタゴラス数

ピタゴラストリプレットは、3つの自然数abcのセットであり、そのために、

a ^ 2 + b ^ 2 = c ^ 2

例えば、

3 ^ 2 + 4 ^ 2 = 9 + 16 = 5 ^ 2 = 25。

a + b + c = N(入力)であるピタゴラストリプレットが1つだけ存在します。

製品abcを見つけます。

プロジェクトオイラー問題9に感謝します 

ピタゴラス(有名な発明者ヘメルディンガーの偶像)の三項は、入力Nが与えられると、a ^ 2 + b ^ 2 = c ^ 2(これはピタゴラスの定理の3つの辺ではありません)を満たします。 ^ 2 + b ^ 2 = c ^ 2およびa + b + c = N。(Abcはすべて自然数です)連立方程式a ^ 2 + b ^ 2 = c ^ 2とa + b + c = N、Nは既知であるため、最初にabcの1つを削除して、他の2つの間を取得できます。 2は最初の式の右端にあり、cを削除してN ^ 2-2aN-2bN + 2ab = 0を取得するのは比較的簡単なので、a =(N ^ 2-2bN)/(2N-2b)、トラバースします。 bであり、aが整数であることを満たします。a<= b <cと仮定すると、a =(N ^ 2-2bN)/(2N-2b)<= bはN ^ 2-4bn + 2b ^ 2 <=になります。 0つまり、(Nb)^ 2 <= 0.5N ^ 2の場合、解はb> = N-sqrt(0.5)Nです。または、b = aの場合、解はa = N /(sqrt(2)+ 2)です。 、したがって、b> = N /(sqrt(2)+2)の場合、cはbより大きいため、2つは同じ意味を持ちます。したがって、最大bはcに無限に近く、bの上限はN / 2です。 、およびそれは望ましくありません。この時点でaが整数であるかどうかを判断するには、bの範囲をトラバースします。abcの積が整数に対して計算される場合は、セットが1つしかないため、それで十分であり、直接返されます。

bも整数である必要があるため、下限を切り上げる必要があり、上限を処理する必要はありません。

function y = euler009(x)
    for b=ceil(x/(sqrt(2)+2)):x/2-1
        a=(x^2-2*b*x)/(2*x-2*b);
        if mod(a,1)==0
            y=a*b*sqrt(a^2+b^2);
            return;
        end
    end
end

プロジェクトオイラー:問題10、素数の合計

10以下の素数の合計は2+ 3 + 5 + 7 = 17です。

入力N以下のすべての素数の合計を求めます。

ありがとう プロジェクトオイラー問題10

与えられた数以下の素数の合計を見つけます。これは前の質問と非常によく似ています。(この質問は簡単とマークされています)

簡単なので、簡単な解決策を見つけてください。

function y = euler010(x)
  y = sum(primes(x));
end

幸い、テストケースはそれほど大きくないため、素数を数えることはできません。

 

以前の一連の質問と比較して、この一連の質問は少し難しいです。ほとんどの質問はしっかりと解決できますが、素数などの特性に基づいていくつかの良い解決策がある質問もあります。直接ループよりはましです。ここでは十分な知識がないので、さようならを言いました。

おすすめ

転載: blog.csdn.net/qq_36614557/article/details/110633423