#include<bits/stdc++.h> usingnamespace std; using uchar = unsignedchar; intmain(){ constint LIMIT = 1000000; // consider primes q < LIMIT // 1) generate all numbers of form 2^i * 3^j < LIMIT grouped by i vector<vector<pair<int,int>>> by_i; // for each i: list of (j, value) int max_i = 0; while((1u<<max_i) < (unsigned)LIMIT) ++max_i; // (1<<max_i) >= LIMIT // ensure max_i covers all i with 2^i <= LIMIT // but we want i from 0 .. max_i-1 by_i.assign(max_i, {}); for(int i=0;i<max_i;++i){ longlong pow2 = 1LL<<i; longlong val = pow2; int j = 0; while(val < LIMIT){ by_i[i].push_back({j, (int)val}); ++j; val = pow2; for(int t=0;t<j; ++t) val *= 3; // slow but j small; we'll fix below // but above is incorrect (recomputes). We'll instead multiply progressively below. break; } } // Re-generate correctly: for each i, multiply by powers of 3 for(int i=0;i<max_i;++i) by_i[i].clear(); for(int i=0;i<max_i;++i){ longlong pow2 = 1LL<<i; longlong v = pow2; int j=0; while(v < LIMIT){ by_i[i].push_back({j,(int)v}); ++j; v *= 3; } } // find max_j across all int max_j = 0; for(auto &vec: by_i) for(auto &pr: vec) max_j = max(max_j, pr.first); // We'll do DP over i (0..max_i-1). State: prev_j index (0..max_j) or special prev = max_j+1 meaning "no previous". int PSTATE = max_j + 2; int MAXS = LIMIT; // sums 0..LIMIT-1 // use two layers of uchar arrays (saturated at 2) vector<uchar> dp_prev((size_t)PSTATE * MAXS); vector<uchar> dp_next((size_t)PSTATE * MAXS); auto idx = [&](int prev, int s){ return prev * MAXS + s; }; int NO_PREV = PSTATE - 1; dp_prev[idx(NO_PREV,0)] = 1; // one way to have sum 0 with no previous chosen
// iterate i for(int i=0;i<max_i;++i){ // start dp_next as copy of dp_prev (option: skip this i) dp_next = dp_prev; // copy // for each possible previous state prev_p and for each allowed choice j in by_i[i] with j < prev_p for(int prev_p=0; prev_p<PSTATE; ++prev_p){ // optimization: skip if whole row is zero bool row_nonzero = false; int base = prev_p * MAXS; for(int s=0;s<MAXS; ++s){ if(dp_prev[base + s]){ row_nonzero = true; break; } } if(!row_nonzero) continue; for(auto &pr: by_i[i]){ int j = pr.first; int val = pr.second; if(prev_p != NO_PREV && j >= prev_p) continue; // must have j < prev_p // add transitions: for all s where dp_prev[prev_p][s] >0, add to dp_next[j][s+val] int dst_base = j * MAXS; for(int s=0; s + val < MAXS; ++s){ uchar ways = dp_prev[base + s]; if(!ways) continue; uchar &dst = dp_next[dst_base + s + val]; int sum = dst + ways; dst = (sum >= 2 ? 2 : sum); // saturate at 2 } } } dp_prev.swap(dp_next); }
// Now for each sum n (1..LIMIT-1) compute total ways P(n) = sum over prev states of dp_prev[prev][n] vector<uchar> Pcount(MAXS); for(int prev=0; prev<PSTATE; ++prev){ int base = prev * MAXS; for(int s=1;s<MAXS;++s){ if(dp_prev[base + s]){ int sum = Pcount[s] + dp_prev[base + s]; Pcount[s] = (sum >= 2 ? 2 : sum); } } }