假设我们有一个整数n,我们必须找到小于或等于n的正整数个数,其中整数个数至少有一个数字出现一次。
因此,如果输入为n = 200,则输出为38
为了解决这个问题,我们将遵循以下步骤-
定义一个数组
对于初始化x:= n,当x为非零时,更新x:= x / 10,执行-
在结尾处插入x mod 10
反转数组
ret:= n
对于初始化w:= 1,d:= 1,当w <a的大小时,更新(w增加1),-
d:= d * min(9,10-w + 1)
ret:= ret − d
定义一个功能go()。这没有任何参数。
对于初始化d:= i <1,当d <a [i]时,更新(将d增加1),执行-
如果((1按位左移a [i])按位AND b)非零,则
除此以外
ret:= ret − x
b:= b XOR(左移a [i] 1位)
返回
b:=(1左移10)-1
对于初始化i:= 0,当i <a的大小时,更新(将i增加1),执行-
(将retret减少1)
调用函数 go()
返回ret
让我们看下面的实现以更好地理解-
#include <bits/stdc++.h>
using namespace std;
int solve(int n) {
   vector<int> a;
   for (int x = n; x; x /= 10) a.push_back(x % 10);
   reverse(a.begin(), a.end());
   int ret = n;
   for (int w = 1, d = 1; w < a.size(); ++w) {
      d *= min(9, 10 − w + 1);
      ret −= d;
   }
   auto go = [&]() {
      int b = (1 << 10) − 1;
      for (int i = 0; i < a.size(); ++i) {
         for (int d = (i < 1); d < a[i]; ++d) {
            int x = 0;
            if ((1 << d) & b) ++x;
               for (int j = i + 1; j < a.size(); ++j) x *= 10 − j;
               ret −= x;
            }
            if ((1 << a[i]) & b)
            b ^= (1 << a[i]);
            else
            return;
         }
         −−ret;
      };
      go();
      return ret;
}
int main(){
   cout << solve(200) << endl;
   return 0;
}200输出结果
38