問題はこちら
問題概要
長さの正整数列が与えられる.以下の条件を満たすをすべて求めよ.- すべてのを満たす整数について,である.
解説1
となるのは,がの任意の素因数を持たないことと同じです.のすべての素因数を求めて,その素因数を持たない以上以下の整数を求められれば良いです.エラトステネスの篩を用いて,以上以下の素数であって,を素因数に持つようなが存在するようなものをで求めます.この素数に対して,以上以下であっての倍数であるような数を,同じくエラトステネスの篩の要領で消していけば残った数が答えとなります.全体の計算量はとなります.
N,M = map(int,input().split()) A = list(map(int,input().split())) maxA = max(max(A),M) k = [True] * (maxA+1) # iが条件を満たすkか(iが使えるか) isprime = [True] * (maxA+1) # iが素数か prime = [] # Aの素因数(使えない素数) # Aの要素は使えない for a in A: k[a] = False # エラトステネスの篩 for i in range(2,maxA+1): if not isprime[i]: continue for j in range(i*2,maxA+1,i): isprime[j] = False # iはjの素因数 # jがAの要素ならiは使えない素数 k[i] = k[i] and k[j] if not k[i]: prime.append(i) # 使えない素数pに対して, pの倍数を使えなくする for p in prime: for j in range(p*2,M+1,p): k[j] = k[j] and k[p] # 使える数をansに入れる ans = [1] for i in range(2,M+1): if k[i]: ans.append(i) # 出力 print(len(ans)) for i in ans: print(i)
解説2
線形篩を用いることででも解けます.の素因数を求め,の倍数を消す,という流れは同じです.
詳しくは実装や以下の記事を参照
計算量は線形篩の方がいいですが,エラトステネスの篩の方が定数倍が軽く実速度は高速です.
提出プログラム
載せました.
https://atcoder.jp/contests/abc215/submissions/25244813 C++ エラトステネスの篩
https://atcoder.jp/contests/abc215/submissions/25253885 C++ 線形篩
https://atcoder.jp/contests/abc215/submissions/25247004 python エラトステネスの篩