classSolution{public:intnumDupDigitsAtMostN(intn){returnn-countSpecialNumbers(n);}private:// Same as 2376. Count Special IntegersintcountSpecialNumbers(intn){constintdigitSize=log10(n)+1;// dp[i][j][k] := # of special integers that belong to the interval// [0, 10^i] with `usedMask` j, where k is 0/1 tight constraintdp.resize(digitSize+1,vector<vector<int>>(1<<10,vector<int>(2,-1)));returncount(to_string(n),digitSize,0,true)-1;// - 0;}vector<vector<vector<int>>>dp;intcount(conststring&s,intdigitSize,intusedMask,boolisTight){if(digitSize==0)return1;if(dp[digitSize][usedMask][isTight]!=-1)returndp[digitSize][usedMask][isTight];intans=0;constintmaxDigit=isTight?s[s.length()-digitSize]-'0':9;for(intdigit=0;digit<=maxDigit;++digit){// `digit` is usedif(usedMask>>digit&1)continue;// Use `digit` nowconstboolnextIsTight=isTight&&(digit==maxDigit);if(usedMask==0&&digit==0)// don't count leading 0s as usedans+=count(s,digitSize-1,usedMask,nextIsTight);elseans+=count(s,digitSize-1,usedMask|1<<digit,nextIsTight);}returndp[digitSize][usedMask][isTight]=ans;}};
classSolution{publicintnumDupDigitsAtMostN(intn){returnn-countSpecialNumbers(n);}// Same as 2376. Count Special IntegersprivateintcountSpecialNumbers(intn){finalintdigitSize=(int)Math.log10(n)+1;// dp[i][j][k] := # of special integers that belong to the interval// [0, 10^i] with `usedMask` j, where k is 0/1 tight constraintdp=newInteger[digitSize+1][1<<10][2];returncount(String.valueOf(n),digitSize,0,true)-1;// - 0;}privateInteger[][][]dp;privateintcount(finalStrings,intdigitSize,intusedMask,booleanisTight){if(digitSize==0)return1;if(dp[digitSize][usedMask][isTight?1:0]!=null)returndp[digitSize][usedMask][isTight?1:0];intans=0;finalintmaxDigit=isTight?s.charAt(s.length()-digitSize)-'0':9;for(intdigit=0;digit<=maxDigit;++digit){// `digit` is usedif((usedMask>>digit&1)==1)continue;// Use `digit` nowfinalbooleannextIsTight=isTight&&(digit==maxDigit);if(usedMask==0&&digit==0)// don't count leading 0s as usedans+=count(s,digitSize-1,usedMask,nextIsTight);elseans+=count(s,digitSize-1,usedMask|1<<digit,nextIsTight);}returndp[digitSize][usedMask][isTight?1:0]=ans;}}
classSolution:defnumDupDigitsAtMostN(self,n:int)->int:returnn-self._countSpecialNumbers(n)def_countSpecialNumbers(self,n:int)->int:s=str(n)digitSize=int(log10(n))+1# Dp(i, j, k) := # Of special integers that beto the interval# [0, 10^i] with `usedMask` j, where k is 0/1 tight constraint@functools.lru_cache(None)defdp(digitSize:int,usedMask:int,isTight:bool)->int:ifdigitSize==0:return1ans=0maxDigit=ord(s[len(s)-digitSize])-ord('0')ifisTightelse9fordigitinrange(maxDigit+1):# `digit` is usedifusedMask>>digit&1:continue# Use `digit` nownextIsTight=isTightand(digit==maxDigit)ifusedMask==0anddigit==0:# don't count leading 0s as usedans+=dp(digitSize-1,usedMask,nextIsTight)else:ans+=dp(digitSize-1,usedMask|1<<digit,nextIsTight)returnansreturndp(digitSize,0,True)-1# - 0