## Editorial for VM 09 Bài 06 - SỐ RÕ RÀNG

Remember to use this editorial

**only**when stuck, and**not to copy-paste code from it**. Please be respectful to the problem author and editorialist.**Submitting an official solution before solving the problem yourself is a bannable offence.****Lưu ý**: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này

#### Code mẫu của flashmt

`#include<iostream> #include<algorithm> #include<string> #include<cstdio> #define fr(a,b,c) for (a=b;a<=c;a++) #define frr(a,b,c) for (a=b;a>=c;a--) #define oo 100000000 using namespace std; int d[1501],tr[1501],ll[1501],nm; long long f[19][10][1501],g[19][1501],re[1501]; void init() { int i,j,l,x,y; fr(i,1,1500) d[i]=-1; d[1]=1; frr(i,1500,2) if (d[i]==-1) { x=i; while (d[x]==-1) { d[x]=0; tr[0]=x; y=0; while (x) { y+=(x%10)*(x%10); x/=10; } x=y; tr[x]=tr[0]; } if (d[x]) do { x=tr[x]; d[x]=1; } while (x!=i); } fr(j,0,9) { f[1][j][j*j]=1; g[i][j*j]=1; } fr(l,2,18) fr(j,0,9) fr(i,j*j,1500) { f[l][j][i]+=g[l-1][i-j*j]; g[l][i]+=f[l][j][i]; } } long long calc(long long n) { int i,j,l=0,a[22],s=0; long long nn=n,res=0; fr(i,1,nm) re[i]=0; while (nn) { a[++l]=nn%10; nn/=10; } while (l) { fr(i,0,a[l]-1) fr(j,1,nm) if (ll[j]>=s) re[j]+=f[l][i][ll[j]-s]; s+=a[l]*a[l]; l--; } fr(i,1,nm) { res+=re[i]; if (ll[i]==s) res++; } return res; } int main() { int test,i; long long n,m,lo,hi,mi; init(); fr(i,1,1500) if (d[i]) ll[++nm]=i; cin >> test; while (test--) { cin >> n >> m; m+=calc(n); lo=1; hi=oo; hi*=oo; while (lo<=hi) { mi=(lo+hi)/2; if (calc(mi)<m) lo=mi+1; else hi=mi-1; } mi--; while (mi<1 || calc(mi)<m) mi++; cout << mi << endl; } return 0; }`

#### Code mẫu của ladpro98

`#include <bits/stdc++.h> const int N = 2000; using namespace std; bool isClear[N], was[N]; long long f[20][2][N]; long long n, kth; vector<int> D; int sumSqr(int x) { int ans = 0; while (x > 0) { ans += (x % 10) * (x % 10); x /= 10; } return ans; } void initialize() { isClear[1] = 1; for (int i = 2; i < N; ++i) { memset(was, 0, sizeof(was)); for (int j = i; !was[j]; j = sumSqr(j)) { was[j] = 1; if (j < i) { isClear[i] = isClear[j]; break; } } } } long long dp(int i, bool bigger, int sum) { if (i < 0) return bigger && isClear[sum]; long long &ans = f[i][bigger][sum]; if (ans != -1 ) return ans; ans = 0; for (int x = (bigger ? 0 : D[i]); x <= 9; ++x) ans += dp(i - 1, bigger | (x > D[i]), sum + x * x); return ans; } void solve() { cin >> n >> kth; long long _n = n; D.clear(); while (_n > 0) { D.push_back(_n % 10); _n /= 10; } D.resize(18); memset(f, -1, sizeof(f)); long long ans = 0; bool bigger = 0; int sum = 0; for (int i = 17; i >= 0; --i) { for (int x = (bigger ? 0 : D[i]); x <= 9; ++x) { long long now = dp(i - 1, bigger | (x > D[i]), sum + x * x); if (kth > now) { kth -= now; } else { ans = ans * 10 + x; bigger |= x > D[i]; sum += x * x; break; } } } cout << ans << '\n'; } int main() { initialize(); int nTest; cin >> nTest; while (nTest--) { solve(); } return 0; }`

#### Code mẫu của RR

`//Written by RR {$ifdef rr} {$mode objfpc} {$inline off} {$r+,q+} {$else} {$mode objfpc} {$inline on} {$r-,q-} {$endif} uses math; const FINP = ''; FOUT = ''; MAXN = 18; MAXK = 1500; isClear : array[1..MAXK] of longint=( 1,0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,1,0,0,1, 0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,1,0,0,0,0,0,0,0, 0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0, 1,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,1,1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,1,0,0,0,0,1,1,0,0,0,0,1,0,0,0, 0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,1,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,1,0,1,1,0,0,0,0,0,1,0,0,0,0,1,0, 0,0,1,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1, 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0, 0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0, 0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0, 0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0, 1,0,0,1,0,0,1,0,0,1,0,1,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1, 0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,1,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0, 1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, 1,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,1,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,1,1, 0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,1,1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,0, 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0); var f1,f2 : text; m,n : int64; test : longint; f : array[0..18,0..1500,0..1] of int64; g : array[0..18,0..1500] of int64; a : array[0..18] of longint; procedure openF; begin assign(f1,FINP); reset(f1); assign(f2,FOUT); rewrite(f2); end; procedure closeF; begin close(f1); close(f2); end; procedure initf; var i,j,now,u:longint; begin fillchar(f,sizeof(f),0); fillchar(g,sizeof(g),0); f[0,0,0]:=1; u:=a[0]; g[0,0]:=1; for i:=0 to MAXN-1 do begin for j:=0 to MAXK do begin if f[i,j,0]>0 then for now:=0 to 9 do if now<a[u] then inc(f[i+1,now*now+j,1],f[i,j,0]) else if now=a[u] then inc(f[i+1,now*now+j,0],f[i,j,0]); if f[i,j,1]>0 then for now:=0 to 9 do inc(f[i+1,now*now+j,1],f[i,j,1]); end; dec(u); if u=0 then break; end; for i:=0 to MAXN-1 do for j:=0 to MAXK do if g[i,j]>0 then for now:=0 to 9 do inc(g[i+1,now*now+j],g[i,j]); end; procedure init(n:int64); var nn:int64; begin fillchar(a,sizeof(a),0); nn:=n; while (n>0) do begin inc(a[0]); a[a[0]]:=n mod 10; n:=n div 10; end; n:=nn; end; function count(n:int64):int64; var i:longint; begin init(n); initf; result:=0; for i:=1 to MAXK do if (f[a[0],i,1]+f[a[0],i,0]>0) and (isClear[i]=1) then inc(result,f[a[0],i,1]+f[a[0],i,0]); end; procedure solve; var s,i,j,now:longint; tt,sum:int64; ok:boolean; begin tt:=count(n)+m; ok:=false; s:=0; for i:=1 to MAXN do for now:=0 to 9 do begin inc(s,now*now); sum:=0; for j:=1 to 1500 do if (isClear[j]=1) and (j>=s) then inc(sum,g[18-i,j-s]); if tt>sum then dec(tt,sum) else begin if ok then write(f2,now) else if (not ok) and (now>0) then begin write(f2,now); ok:=true; end; break; end; dec(s,now*now); end; writeln(f2); end; begin openF; read(f1,test); for test:=1 to test do begin read(f1,n,m); solve; end; closeF; end.`

#### Code mẫu của ll931110

`{$MODE DELPHI} program CLEAR4; const input = ''; output = ''; maxd = 20; maxs = 81; maxk = maxd * maxs; var fi,fo: text; i,t: integer; n,m: qword; free: array[1..maxk] of boolean; list: array[1..maxk] of integer; nlist: integer; d: array[1..maxd] of integer; F: array[-1..9,1..maxd,0..maxk] of qword; procedure openfile; begin assign(fi, input); reset(fi); assign(fo, output); rewrite(fo); end; procedure genshappy; var i,ss,k,tmp: integer; begin fillchar(free, sizeof(free), true); free[4] := false; for i := 1 to maxk do if free[i] then begin ss := i; repeat k := ss; ss := 0; while k <> 0 do begin tmp := k mod 10; ss := ss + sqr(tmp); k := k div 10; end; if ss = 1 then break; if not free[ss] then begin free[i] := false; break; end; until false; end; nlist := 0; for i := 1 to maxk do if free[i] then begin inc(nlist); list[nlist] := i; end; end; procedure gensnum; var i,j,k,fs: integer; begin fillchar(F, sizeof(F), 0); for i := 0 to 9 do F[i,1,i * i] := 1; for j := 2 to maxd do for i := 0 to 9 do for k := sqr(i) to j * maxs do for fs := 0 to 9 do F[i,j,k] := F[i,j,k] + F[fs,j - 1,k - sqr(i)]; end; function calc(k,c: integer): qword; var i,j,s: integer; tmp: qword; begin if k = 0 then exit(0); s := d[k]; if k > 1 then dec(s); tmp := 0; for i := 0 to s do for j := 1 to nlist do if list[j] >= c then tmp := tmp + F[i,k,list[j] - c]; calc := tmp + calc(k - 1,c + sqr(d[k])); end; procedure solve; var k,i,j,delta,digit: integer; count,curr,next: qword; begin readln(fi, n, m); fillchar(d, sizeof(d), 0); k := 0; while n > 0 do begin inc(k); d[k] := n mod 10; n := n div 10; end; m := m + calc(k,0); delta := 0; j := 0; count := 0; while count < m do begin inc(j); for i := 1 to 9 do for k := 1 to nlist do count := count + F[i,j,list[k]]; end; k := j; fillchar(d, sizeof(d), 0); for j := k downto 1 do begin digit := 0; curr := 0; next := 0; while next < m do begin curr := next; for k := 1 to nlist do if list[k] >= delta then next := next + F[digit,j,list[k] - delta]; inc(digit); end; m := m - curr; dec(digit); d[j] := digit; delta := delta + sqr(digit); end; end; procedure printresult; var i,k: integer; begin k := maxd; while d[k] = 0 do dec(k); for i := k downto 1 do write(fo, d[i]); writeln(fo); end; procedure closefile; begin close(fo); close(fi); end; begin openfile; genshappy; gensnum; readln(fi, t); for i := 1 to t do begin solve; printresult; end; closefile; end.`

#### Code mẫu của khuc_tuan

`#include <iostream> using namespace std; bool mark[2000]; int c[20], nc; long long result; long long F[17][2][1500]; int sum2(int x) { if(x < 10) return x * x; else return (x % 10) * (x % 10) + sum2(x / 10); } long long go(int pos, bool isgreater, int total, long long cur, long long m) { if(m <= 0) return 0; if(pos == -1) { if(mark[total] && isgreater) { if(m == 1) result = cur; return 1; } return 0; } long long &ret = F[pos][isgreater][total], tmp; if(ret != -1 && ret < m) return ret; ret = 0; for(int ad=0;ad<10;++ad) if(isgreater || ad >= c[pos]) { tmp = go( pos - 1, isgreater || ad > c[pos], total + ad * ad, cur * 10 + ad, m); m -= tmp; ret += tmp; } return ret; } int main() { for(int i=1;i<2000;++i) { int x = i; for(int k=0;k<1000;++k) x = sum2(x); mark[i] = (x == 1); } int st; long long n, m; cin >> st; for(int k=0;k<st;++k) { cin >> n >> m; memset( c, 0, sizeof(c)); for(nc = 0; n > 0; n /= 10) c[nc++] = n % 10; memset( F, -1, sizeof(F)); go(16, 0, 0, 0, m); cout << result << endl; } return 0; }`

## Comments