SlideShare une entreprise Scribd logo
1  sur  9
Télécharger pour lire hors ligne
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

Contenu connexe

Tendances

ロックフリーGCLOCKページ置換アルゴリズム
ロックフリーGCLOCKページ置換アルゴリズムロックフリーGCLOCKページ置換アルゴリズム
ロックフリーGCLOCKページ置換アルゴリズム
Makoto Yui
 

Tendances (20)

AtCoder Beginner Contest 012 解説
AtCoder Beginner Contest 012 解説AtCoder Beginner Contest 012 解説
AtCoder Beginner Contest 012 解説
 
Trianguler
TriangulerTrianguler
Trianguler
 
AtCoder Beginner Contest 015 解説
AtCoder Beginner Contest 015 解説AtCoder Beginner Contest 015 解説
AtCoder Beginner Contest 015 解説
 
AtCoder Beginner Contest 030 解説
AtCoder Beginner Contest 030 解説AtCoder Beginner Contest 030 解説
AtCoder Beginner Contest 030 解説
 
AtCoder Beginner Contest 033 解説
AtCoder Beginner Contest 033 解説AtCoder Beginner Contest 033 解説
AtCoder Beginner Contest 033 解説
 
直前合宿 講義スライド
直前合宿 講義スライド直前合宿 講義スライド
直前合宿 講義スライド
 
AtCoder Regular Contest 020 解説
AtCoder Regular Contest 020 解説AtCoder Regular Contest 020 解説
AtCoder Regular Contest 020 解説
 
abc027
abc027abc027
abc027
 
2SAT(充足可能性問題)の解き方
2SAT(充足可能性問題)の解き方2SAT(充足可能性問題)の解き方
2SAT(充足可能性問題)の解き方
 
AtCoder Regular Contest 022 解説
AtCoder Regular Contest 022 解説AtCoder Regular Contest 022 解説
AtCoder Regular Contest 022 解説
 
AtCoder Regular Contest 023 解説
AtCoder Regular Contest 023 解説AtCoder Regular Contest 023 解説
AtCoder Regular Contest 023 解説
 
AtCoder Regular Contest 024 解説
AtCoder Regular Contest 024 解説AtCoder Regular Contest 024 解説
AtCoder Regular Contest 024 解説
 
AtCoderに毎回参加したくなる仕組み
AtCoderに毎回参加したくなる仕組みAtCoderに毎回参加したくなる仕組み
AtCoderに毎回参加したくなる仕組み
 
AtCoder Beginner Contest 014 解説
AtCoder Beginner Contest 014 解説AtCoder Beginner Contest 014 解説
AtCoder Beginner Contest 014 解説
 
ARC#003D
ARC#003DARC#003D
ARC#003D
 
AtCoder Beginner Contest 029 解説
AtCoder Beginner Contest 029 解説AtCoder Beginner Contest 029 解説
AtCoder Beginner Contest 029 解説
 
AtCoder Regular Contest 033 解説
AtCoder Regular Contest 033 解説AtCoder Regular Contest 033 解説
AtCoder Regular Contest 033 解説
 
リーン顧客開発
リーン顧客開発リーン顧客開発
リーン顧客開発
 
ロックフリーGCLOCKページ置換アルゴリズム
ロックフリーGCLOCKページ置換アルゴリズムロックフリーGCLOCKページ置換アルゴリズム
ロックフリーGCLOCKページ置換アルゴリズム
 
AtCoder Beginner Contest 011 解説
AtCoder Beginner Contest 011 解説AtCoder Beginner Contest 011 解説
AtCoder Beginner Contest 011 解説
 

Plus de paiza

Plus de 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