GCDの問題、いろいろあるなぁ。
https://yukicoder.me/problems/no/2081
問題
整数Mが与えられる。
1~100000の範囲の整数の部分集合Sのうち、以下を満たすものを998244353で割った余りがMとなるものを1つ答えよ。
- Sの部分集合のうち、GCDが2以上になるもの
解法
素数aに対し、aおよびaに(aと素な)素数を掛けたものを計n個準備すれば、GCDがaとなるものを(2^n)-1手配できる。
(2^n)-1≦Mとなるnに対し、未使用の素数をn個使う、ということを繰り返せばよい。
const int prime_max = 100000; set<int> prime; int NP,divp[prime_max]; void cprime() { if(NP) return; for(int i=2;i<prime_max;i++) if(divp[i]==0) { //M[i]=NP; prime.insert(i); NP++; for(ll j=1LL*i*i;j>=i&&j<prime_max;j+=i) if(divp[j]==0) divp[j]=i; } } ll M; void solve() { int i,j,k,l,r,x,y; string s; cin>>M; cprime(); vector<int> V; if(M==0) V={1}; while(M) { int n=0; while((1<<(n+1))-1<=M) n++; M-=(1<<n)-1; int a=*prime.begin(); prime.erase(a); V.push_back(a); n--; while(n) { int b=*prime.rbegin(); prime.erase(b); if(a*b<=100000) { n--; V.push_back(a*b); } } } cout<<V.size()<<endl; FORR(v,V) cout<<v<<" "; cout<<endl; }
まとめ
思いついてしまえばすぐ。