AtCoder最強学生戦

第一回日本最強プログラマー学生選手権‐予選‐のネタバレを含みます.

https://atcoder.jp/contests/jsc2019-qual/tasks

A-Takahashi Calendar

今日は珍しい積の日(8=2*4)らしく,それに関する問題でした.この問題では,与えられた月と日から高橋暦を作り,そのときの積の日の回数を数えよ,という問題でした. コードは以下の通り.

M, D = map(int,input().split())
ans = 0
if D < 10:
  print(ans)
  exit()
for i in range(1,M+1):
  for j in range(10,D+1):
    if i == (j % 10) * ((j//10) % 10) and (j % 10) != 1 and ((j//10) % 10) != 1:
      ans += 1
print(ans)

まず,Dが1桁なら,2桁の数が0になるため積の日はなく,0を出力して終了します. で,それ以外ならfor文二重に回して,mod10で位の数を取り出していきます.

B-Kleene Inversion 与えられた整数列AをK回繰り返した整数列をBとして,Bの転倒数109+7で割った余りを出力しろとのこと.ここでいう転倒数とは,整数の順序対(i,j)(0<=i<j<K*N-1)であってBi>Bjを満たすもの,らしいです. コードは以下の通り.

N, K =map(int,input().split())
A = list(map(int,input().split()))
A2 = A*2
ans = 0
tento = 0
ibitsu = 0
for i in range(len(A)):
  for j in range(i,len(A)):
    if A[i] > A[j]:
      ans += 1
for i in range(len(A2)):
  for j in range(i,len(A2)):
    if A2[i] > A2[j]:
      ibitsu += 1
#print(ibitsu,ans)
ibitsu -= ans*2
#print(ibitsu)
ibitsu = ibitsu * K*(K-1)//2
#print(ibitsu)
ans *= K
ans += ibitsu
print(ans % (10**9+7))

最初の二重ループでは左から右の転倒数を数えて,ansに入れています.

2つ目の二重ループは意味わからないと思いますが,Aを二回繰り返したものをA2とし,そこでカウントした転倒数にibitsuと名付け(だって図描いてるとき歪やってんもん),そこからans*2を引いています.ほんまネーミングセンス0やな自分.

そして,ibitsuのほうは1からK-1までの総和をかけて(内部だからね),ansのほうには繰り返し数K(辺だからね)をかけて両方の和が答えとなります.

PyPy3で書くと300msほどかかったので,Nimだとどれくらいかなと思い,Nimで書き直すと思ったよりオーバーフローに困りました.Pythonだとオーバーフローを考える必要がないので. まあしかしNimだと8msくらいだったので,やっぱり速いなと思いました.

パフォーマンスは914でした.

感想

自分的には初の緑パフォーマンスで,上々の出来でした.なかなかにCの意味・解き方がわからなかったので,これより上は少し遠いのかな,と思いました.

また,本番になるとPythonに頼ってしまう(というか過去問解きのときからそう)ので,AtCoderにおけるPython を一時封印して,Nimで書くことにしようと思います.