SlideShare a Scribd company logo
1 of 9
Download to read offline
029_mod7占い【上級・ 
アルゴリズム】解説 
ギノ株式会社 吉岡 恒夫
問題 
• 問題: https://paiza.jp/learning/mod7 
• あなたは今、「mod7占い」というサービスを始めようと考えています。 
• mod7占いとは、整数が書かれた複数のカードの中から3枚を選び、そこ 
に書かれた整数の和が7で割り切れるかどうかで運勢を決めようというも 
のです。 カードは必ず異なる3枚を選ぶ必要があり、全てのカードには全 
て異なる数字が書かれています。 
• 占いというからには、7で割り切れる組み合わせはそれなりに少なくする 
必要があります。 そこで、適当な複数のカードに対して、カードに書か 
れた3つの整数を足した和が7で割り切れるような組合せがいくつあるか 
を計算するプログラムを作成してください。
問題まとめ 
• N個の数列a_iから3つを選ぶ 
• 3つの数字の合計が7で割り切れる組み合わせの 
数を出力する。 
• 1≤N≤100,000 
0≤a_i < 2^32
解法1 
(総当たり) 
• 1つ目の数字を選ぶループ 
• 2つ目の数字を選ぶループ 
• 3つ目の数字を選ぶループ 
• 合計が7で割り切れるか確認
解法1(計算量) 
• 三重ループ 
• 組み合わせの数: C(N, 3) = N*(N-1)*(N-2)/6 = 
166,661,666,700,000 (n=100,000) 
• 計算量: O(N^3) 
• 無理~
解法2 
• 足す前に剰余を取っても、結果は変わらない。 
(A+B)%7 = (A%7 + B%7 + C%7)%7 
• 0~6の値のみ与えられたと考えてよい。 
• 3つを選ぶ組み合わせは 7 * 7 * 7 = 343
解法2 
• 各a_iについて、7で割った余り0-6の出現回数を数える。 
• 0-6の数字から1つめの数字を選ぶループ 
• 0-6の数字から2つめの数字を選ぶループ 
• 0-6の数字から3つめの数字を選ぶループ 
• 組み合わせの数を計算 
1つめの数、2つめの数、3つめの数、 
の出現回数を掛け合わせる 
2つの数字が同じ場合、重複を除くため重複の片方を1引いて、2で割 
る 
3つの数字が同じ場合、重複を除くため重複の片方を1もう片方を2引 
いて、6で割る
コード
N= 
gets.to_i 
counts 
= 
Array.new(7,0) 
STDIN.read.split.map(&:to_i).map{|i| 
i%7}.each{|a| 
counts[a] 
+= 
1 
} 
total 
= 
0 
(0..6).each{|i| 
(i..6).each{|j| 
(j..6).each{|k| 
next 
if 
(i+j+k)%7 
!= 
0 
c1 
= 
counts[i] 
c2 
= 
counts[j] 
c3 
= 
counts[k] 
c2 
-­‐= 
1 
if 
i 
== 
j 
c3 
-­‐= 
1 
if 
k 
== 
i 
c3 
-­‐= 
1 
if 
k 
== 
j 
pat 
= 
c1*c2*c3 
if 
i==j 
&& 
j==k 
pat 
/= 
6 
elsif 
i==j 
|| 
i==k 
|| 
j==k 
pat 
/= 
2 
end 
total 
+= 
pat 
} 
} 
} 
puts 
total

More Related Content

What's hot

AtCoder Beginner Contest 010 解説
AtCoder Beginner Contest 010 解説AtCoder Beginner Contest 010 解説
AtCoder Beginner Contest 010 解説AtCoder Inc.
 
AtCoder Beginner Contest 021 解説
AtCoder Beginner Contest 021 解説AtCoder Beginner Contest 021 解説
AtCoder Beginner Contest 021 解説AtCoder Inc.
 
AtCoder Beginner Contest 022 解説
AtCoder Beginner Contest 022 解説AtCoder Beginner Contest 022 解説
AtCoder Beginner Contest 022 解説AtCoder Inc.
 
AtCoder Beginner Contest 015 解説
AtCoder Beginner Contest 015 解説AtCoder Beginner Contest 015 解説
AtCoder Beginner Contest 015 解説AtCoder Inc.
 
AtCoder Beginner Contest 029 解説
AtCoder Beginner Contest 029 解説AtCoder Beginner Contest 029 解説
AtCoder Beginner Contest 029 解説AtCoder Inc.
 
AtCoder Beginner Contest 004 解説
AtCoder Beginner Contest 004 解説AtCoder Beginner Contest 004 解説
AtCoder Beginner Contest 004 解説AtCoder Inc.
 
AtCoder Regular Contest 026 解説
AtCoder Regular Contest 026 解説AtCoder Regular Contest 026 解説
AtCoder Regular Contest 026 解説AtCoder Inc.
 
短時間発話を用いた話者照合のための音声加工の効果に関する検討
短時間発話を用いた話者照合のための音声加工の効果に関する検討短時間発話を用いた話者照合のための音声加工の効果に関する検討
短時間発話を用いた話者照合のための音声加工の効果に関する検討Shinnosuke Takamichi
 
最小カットを使って「燃やす埋める問題」を解く
最小カットを使って「燃やす埋める問題」を解く最小カットを使って「燃やす埋める問題」を解く
最小カットを使って「燃やす埋める問題」を解くshindannin
 
とぽろじー入門(画像なし版)
とぽろじー入門(画像なし版)とぽろじー入門(画像なし版)
とぽろじー入門(画像なし版)Katsuya Ito
 
Solving Poisson Equation using Conjugate Gradient Method and its implementation
Solving Poisson Equation using Conjugate Gradient Methodand its implementationSolving Poisson Equation using Conjugate Gradient Methodand its implementation
Solving Poisson Equation using Conjugate Gradient Method and its implementationJongsu "Liam" Kim
 
CODE FESTIVAL 2015 予選A 解説
CODE FESTIVAL 2015 予選A 解説CODE FESTIVAL 2015 予選A 解説
CODE FESTIVAL 2015 予選A 解説AtCoder Inc.
 
AtCoder Regular Contest 037 解説
AtCoder Regular Contest 037 解説AtCoder Regular Contest 037 解説
AtCoder Regular Contest 037 解説AtCoder Inc.
 

What's hot (20)

AtCoder Beginner Contest 010 解説
AtCoder Beginner Contest 010 解説AtCoder Beginner Contest 010 解説
AtCoder Beginner Contest 010 解説
 
AtCoder Beginner Contest 021 解説
AtCoder Beginner Contest 021 解説AtCoder Beginner Contest 021 解説
AtCoder Beginner Contest 021 解説
 
t-SNE Explained
t-SNE Explainedt-SNE Explained
t-SNE Explained
 
AtCoder Beginner Contest 022 解説
AtCoder Beginner Contest 022 解説AtCoder Beginner Contest 022 解説
AtCoder Beginner Contest 022 解説
 
最大流 (max flow)
最大流 (max flow)最大流 (max flow)
最大流 (max flow)
 
明日使えないすごいビット演算
明日使えないすごいビット演算明日使えないすごいビット演算
明日使えないすごいビット演算
 
Abc009
Abc009Abc009
Abc009
 
目指せグラフマスター
目指せグラフマスター目指せグラフマスター
目指せグラフマスター
 
AtCoder Beginner Contest 015 解説
AtCoder Beginner Contest 015 解説AtCoder Beginner Contest 015 解説
AtCoder Beginner Contest 015 解説
 
AtCoder Beginner Contest 029 解説
AtCoder Beginner Contest 029 解説AtCoder Beginner Contest 029 解説
AtCoder Beginner Contest 029 解説
 
AtCoder Beginner Contest 004 解説
AtCoder Beginner Contest 004 解説AtCoder Beginner Contest 004 解説
AtCoder Beginner Contest 004 解説
 
AtCoder Regular Contest 026 解説
AtCoder Regular Contest 026 解説AtCoder Regular Contest 026 解説
AtCoder Regular Contest 026 解説
 
Za atsu-20170328
Za atsu-20170328Za atsu-20170328
Za atsu-20170328
 
短時間発話を用いた話者照合のための音声加工の効果に関する検討
短時間発話を用いた話者照合のための音声加工の効果に関する検討短時間発話を用いた話者照合のための音声加工の効果に関する検討
短時間発話を用いた話者照合のための音声加工の効果に関する検討
 
最小カットを使って「燃やす埋める問題」を解く
最小カットを使って「燃やす埋める問題」を解く最小カットを使って「燃やす埋める問題」を解く
最小カットを使って「燃やす埋める問題」を解く
 
とぽろじー入門(画像なし版)
とぽろじー入門(画像なし版)とぽろじー入門(画像なし版)
とぽろじー入門(画像なし版)
 
Solving Poisson Equation using Conjugate Gradient Method and its implementation
Solving Poisson Equation using Conjugate Gradient Methodand its implementationSolving Poisson Equation using Conjugate Gradient Methodand its implementation
Solving Poisson Equation using Conjugate Gradient Method and its implementation
 
CODE FESTIVAL 2015 予選A 解説
CODE FESTIVAL 2015 予選A 解説CODE FESTIVAL 2015 予選A 解説
CODE FESTIVAL 2015 予選A 解説
 
abc027
abc027abc027
abc027
 
AtCoder Regular Contest 037 解説
AtCoder Regular Contest 037 解説AtCoder Regular Contest 037 解説
AtCoder Regular Contest 037 解説
 

More from paiza

paizaのオンラインジャッジを支えるDockerとその周辺
paizaのオンラインジャッジを支えるDockerとその周辺paizaのオンラインジャッジを支えるDockerとその周辺
paizaのオンラインジャッジを支えるDockerとその周辺paiza
 
141214_paizaでpizzaもぐもぐ勉強会
141214_paizaでpizzaもぐもぐ勉強会141214_paizaでpizzaもぐもぐ勉強会
141214_paizaでpizzaもぐもぐ勉強会paiza
 
シリコンバレー 面接体験
シリコンバレー 面接体験シリコンバレー 面接体験
シリコンバレー 面接体験paiza
 
ハノイの塔 解説
ハノイの塔 解説ハノイの塔 解説
ハノイの塔 解説paiza
 
paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説
paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説
paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説paiza
 
【社内勉強会資料】自社サービスエンジニアの為の「UX設計と情報設計」
【社内勉強会資料】自社サービスエンジニアの為の「UX設計と情報設計」【社内勉強会資料】自社サービスエンジニアの為の「UX設計と情報設計」
【社内勉強会資料】自社サービスエンジニアの為の「UX設計と情報設計」paiza
 

More from paiza (6)

paizaのオンラインジャッジを支えるDockerとその周辺
paizaのオンラインジャッジを支えるDockerとその周辺paizaのオンラインジャッジを支えるDockerとその周辺
paizaのオンラインジャッジを支えるDockerとその周辺
 
141214_paizaでpizzaもぐもぐ勉強会
141214_paizaでpizzaもぐもぐ勉強会141214_paizaでpizzaもぐもぐ勉強会
141214_paizaでpizzaもぐもぐ勉強会
 
シリコンバレー 面接体験
シリコンバレー 面接体験シリコンバレー 面接体験
シリコンバレー 面接体験
 
ハノイの塔 解説
ハノイの塔 解説ハノイの塔 解説
ハノイの塔 解説
 
paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説
paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説
paizaオンラインハッカソン(略してPOH![ポー!])Lite「天才火消しエンジニア霧島 もしPMおじさんが『丸投げ』を覚えたら」解説
 
【社内勉強会資料】自社サービスエンジニアの為の「UX設計と情報設計」
【社内勉強会資料】自社サービスエンジニアの為の「UX設計と情報設計」【社内勉強会資料】自社サービスエンジニアの為の「UX設計と情報設計」
【社内勉強会資料】自社サービスエンジニアの為の「UX設計と情報設計」
 

mod7占い【上級・アルゴリズム】解説

  • 2. 問題 • 問題: https://paiza.jp/learning/mod7 • あなたは今、「mod7占い」というサービスを始めようと考えています。 • mod7占いとは、整数が書かれた複数のカードの中から3枚を選び、そこ に書かれた整数の和が7で割り切れるかどうかで運勢を決めようというも のです。 カードは必ず異なる3枚を選ぶ必要があり、全てのカードには全 て異なる数字が書かれています。 • 占いというからには、7で割り切れる組み合わせはそれなりに少なくする 必要があります。 そこで、適当な複数のカードに対して、カードに書か れた3つの整数を足した和が7で割り切れるような組合せがいくつあるか を計算するプログラムを作成してください。
  • 3. 問題まとめ • N個の数列a_iから3つを選ぶ • 3つの数字の合計が7で割り切れる組み合わせの 数を出力する。 • 1≤N≤100,000 0≤a_i < 2^32
  • 4. 解法1 (総当たり) • 1つ目の数字を選ぶループ • 2つ目の数字を選ぶループ • 3つ目の数字を選ぶループ • 合計が7で割り切れるか確認
  • 5. 解法1(計算量) • 三重ループ • 組み合わせの数: C(N, 3) = N*(N-1)*(N-2)/6 = 166,661,666,700,000 (n=100,000) • 計算量: O(N^3) • 無理~
  • 6. 解法2 • 足す前に剰余を取っても、結果は変わらない。 (A+B)%7 = (A%7 + B%7 + C%7)%7 • 0~6の値のみ与えられたと考えてよい。 • 3つを選ぶ組み合わせは 7 * 7 * 7 = 343
  • 7. 解法2 • 各a_iについて、7で割った余り0-6の出現回数を数える。 • 0-6の数字から1つめの数字を選ぶループ • 0-6の数字から2つめの数字を選ぶループ • 0-6の数字から3つめの数字を選ぶループ • 組み合わせの数を計算 1つめの数、2つめの数、3つめの数、 の出現回数を掛け合わせる 2つの数字が同じ場合、重複を除くため重複の片方を1引いて、2で割 る 3つの数字が同じ場合、重複を除くため重複の片方を1もう片方を2引 いて、6で割る
  • 9. N= gets.to_i counts = Array.new(7,0) STDIN.read.split.map(&:to_i).map{|i| i%7}.each{|a| counts[a] += 1 } total = 0 (0..6).each{|i| (i..6).each{|j| (j..6).each{|k| next if (i+j+k)%7 != 0 c1 = counts[i] c2 = counts[j] c3 = counts[k] c2 -­‐= 1 if i == j c3 -­‐= 1 if k == i c3 -­‐= 1 if k == j pat = c1*c2*c3 if i==j && j==k pat /= 6 elsif i==j || i==k || j==k pat /= 2 end total += pat } } } puts total