---
# System prepended metadata

title: ARC 173A

---

## AtCoder Regular Contest 173A - Neq Number

[<<回主頁](https://hackmd.io/@r1cky/Sk2hKzga6)

### 前言

打的時候過範測但一直 WA ，痛苦面具

### 解法

先想另外一題 :

> 給你一個正整數 $x$，我們想知道 $x$ 以下的 Neq Number 有幾個。

這個可以利用 digit dp 來解決。

定義 $dp_{d,i}$ 代表上一個填 $i$，然後後面 $d$ 位的選填方法，這裡的 $dp$ 是沒有限制的狀態(也就是沒有上界限制)，接著特別處理貼著上界的 case 可以 $O(logx)$ 求出來。

那回到原題，我們可以二分搜答案，那每次就是檢查 $mid$ 以下的 Neq Number 和題目給的 $K$ 的數量關係決定左右界的調整，時間複雜度為 $O(Nlog^2K)$。

### code

```cpp=
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#include <bits/stdc++.h>
#define i64 long long
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;

const i64 maxn = (i64)1e18;
const int ma = 18;
i64 dp[ma+5][11];

i64 qpow(i64 x, i64 pw){
    i64 res = 1;
    while(pw){
        if(pw & 1) res *= x;
        x *= x;
        pw >>= 1;
    }
    return res;
}

i64 DP(i64 x, i64 ten, int idx, int pre, int zero, int lim){
    if(!idx) return 1;
    if(dp[idx][pre] != -1 && !zero && !lim) return dp[idx][pre];
    int go = (x / ten) % 10;
    i64 ans = 0;
    if(!lim) go = 9;
    for(int my = 0; my <= go; my++){
        if(my == pre) continue;
        if(!my && zero) {
            ans += DP(x, ten/10, idx-1, 10, 1, lim && (my == go));
        }
        else{
            ans += DP(x, ten/10, idx-1, my, 0, lim && (my == go));
        }
    }
    return dp[idx][pre] = ans;
}

int check(i64 x, i64 need){
    memset(dp, -1, sizeof(dp));
    return (DP(x, maxn/10, ma, -1, 1, 1) - 1) < need;
}
int main() {
    IOS;
    int n;
    i64 k;
    cin >> n;
    while(n--){
        cin >> k;
        i64 l = 1, r = (i64)1e18 - 1;
        while (l != r){
            i64 mid = (l + r) >> 1;
            if(check(mid, k)){
                l = mid + 1;
            }
            else{
                r = mid;
            }
        }
        cout << l << '\n';
    }
}
```


### 然後

聽說這題有酷酷數學構造解，如果有人知道怎麼構可以在下方留言，謝謝。

