0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CodeIQ:「ディビジョン・サム」問題

Last updated at Posted at 2024-09-07

Kawazoe(@riverplus)さんのCodeIqの問題です。
問題はこちらの御世話になりました。解答例もあります。
->https://sw-logic.com/Portfolio/Programing/CodeIQ/2903.php
こちらにも情報があります。
->https://togetter.com/li/1049668
テストケースはあちこちから集めた気がします。

例えばz=x^2*y^3(x,y素因数)とすると、zの約数は、
 x^0*y^0,x^0*y^1,x^0*y^2,x^0*y^3
 x^1*y^0,x^1*y^1,x^1*y^2,x^1*y^3
 x^2*y^0,x^2*y^1,x^2*y^2,x^2*y^3
となり合計は
x^0*Σ(0<=k<=3)(y^k)+x^1*Σ(0<=k<=3)(y^k)+x^2*Σ(0<=k<=3)(y^k)
=Σ(0<=h<=2)(x^h)*Σ(0<=k<=3)(y^k)
素因数やその指数が増えても同様です。
更にΣ(0<=h<=m)(x^h)=(x^(m+1)-1)/(x-1)
そしてn!^nのある素因数の指数はn!のその素因数の指数のn倍です。

Juliaではfactorが使えますがパッケージをインストールしないといけませんので、
自前で(n!)^nの素因数を調べるfactor1を実装しました。
n!の素因数分解はルジャンドル関数を用いて求めることができます。
つまりn!を素因数分解すると素数pの数はΣ(p<=p^i<=n)div(n,p^i)
factor1では同時に素数も求めています。n以下のすべての素数が素因数です。
その後約数の和の計算をします。結果は大きな数になりますのでBigIntを使います。
(BigIntを使わないとinvmodという関数が必要のよう)
2024.9.7追加->カッコ内はinvmodを使った場合のみ解けたという意味です。

#import Pkg;Pkg.add("Primes")
#import Primes: isprime, primes, primesmask, factor

 function solve46(n,a)
  function factor1(n)
  #ルジャンドル関数を利用
    for i in 2 : n
      x = 0
      if ar2[i] != 0  # iが素数なら
        k = i
        for j in i : i : n
           ar2[j] = 0  # iの倍数は素数ではない 
           if j == k    # jはiの累乗
              x += div(n,j)
              k *= i  # kはiの累乗 
           end
        end
        ar1[i] = x*n
      end  
    end
  end
  ar1 = zeros(Int,n)
  ar2 = Array(1:1:n)
  m = 1000003
  ret = big(1)
  factor1(n)
  for i in 2 : n
    if ar1[i] != 0
       x = big(i)
       ret = mod(ret * div(x^(ar1[x]+1)-1,x-1),m)
    end
  end
  s = a == ret ? "ok " : "no "
  println(s,ret)
end

solve46(2, 7)
solve46(3, 600)
solve46(4, 991111)
solve46(12, 845575)
solve46(630, 951018)
solve46(997, 772380)
solve46(1000, 985788)

Prologではコードが複雑にならないように先に素数を求めています。
それでfactor/4はルジャンドル関数だけを実装していますので
NをK^iで割るのではなく、
NをKで割った商をさらにKで割りつつ商を合計しています。
その後calc44で約数の和を計算します。
sumfac/2では素数のリストと、素因数の数を入れるリストを作ってfac/4を呼び、
fac4ではすべての素数をfactor/4に送り、結果をN倍してリストに入れています。
SWI-Prologは多倍長整数ですので、大きな数でも問題ありません。
(投稿時私の環境ではideoneでJavaしか表示されず実行できません)

%SWI-Prolog ver 7.42,7.64,9.25
%:-initialization(start).   %(Online Prolog Compiler.)
%start.

factor(N,X,R,R):-X>N,!.
factor(N,X,R1,R):-N1 is N div X,R2 is R1+N1,factor(N1,X,R2,R).

fac([],_,R,R):-!.
fac([H|P],N,L,R):-
   factor(N,H,0,V),V1 is V*N,
   nth1(H,L,_,L1),nth1(H,R1,V1,L1),fac(P,N,R1,R),!.

sumfac(N,R):-length(L,N),maplist(=(0),L),prime(N,P),fac(P,N,L,R).

prime(2,[2]).
prime(N,R):-
   N1 is N-1,prime(N1,R1),
   (forall(member(X,R1),(N mod X=\=0))->R=[N|R1];R=R1).

calc(1,_,1).
calc(N,L,R):-
   N1 is N-1,calc(N1,L,R1),nth1(N,L,X),
   (X=:=0->Y=1;Y is (N^(X+1)-1) div (N-1)),R is (R1*Y) mod 1000003.

solve(N,R):-sumfac(N,L),calc(N,L,R1),R is R1,!.% mod 1000003,!.

start:-
   f(N,A),(solve(N,R)->(R==A->Str=" ok  ";Str=" no  ");
    write(fail)),write(" "),write(Str),writeln(R),fail.
start.

f(2, 7).
f(3, 600).
f(4, 991111).
f(12, 845575).
f(630, 951018).
f(997, 772380).
f(1000, 985788).

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?