Luogu P2022 有趣的數

2022-05-16 07:41:07 字數 3144 閱讀 2504

讓我們來考慮1到n的正整數集合。讓我們把集合中的元素按照字典序排列,例如當n=11時,其順序應該為:1,10,11,2,3,4,5,6,7,8,9。

定義k在n個數中的位置為q(n,k),例如q(11,2)=4。現在給出整數k和m,要求找到最小的n,使得q(n,k)=m。

輸入檔案只有一行,是兩個整數k和m。

輸出檔案只有一行,是最小的n,如果不存在這樣的n就輸出0。

2 4
11
100000001 1000000000
100000000888888879
\(40\%\)的資料,\(1<=k\),\(m<=10^5\);

\(100\%\)的資料,\(1<=k\),\(m<=10^9\)。

參照此篇題解

由於 \(m\) 是 \(k\) 的位次, 所以有 \(m - 1\) 個數排在其之前.

顯然這個題主要討論的就是有多少個數在 \(k\) 之前, 所以首先將 \(m\) 變成 \(m - 1\), 將問題轉化.

既然不能二分, 尋找此題其他性質, 有 \(n - 1\) 個數排在 \(k\) 前面, 且相同位數的數字是連續出現的. 即排序後, 位數不同的數會排成幾個個公差為 \(1\) 的數列, 如 \(q(11, 9) = 11的排列\)

\[\

\]將 \(9\) 前面的數字排序後:

\[\\]

可以看到從 \(1\) 到, \(8\), 從 \(10\) 到 \(11\) 是連續的.

所以可以嘗試按位數來列舉排在 \(k\) 前面的數.

由最開始 \(q(n, k)\) 隨 \(n\) 單調遞增可得, 對於每乙個 \(k\), 一定存在

\[q(k, k) \leq q(n, k)\ ,\ (n \geq k)

\]用 \(min\) 存 \(q(k, k) - 1\), 可以判斷是否有解, 並且作為求解的第一步.

如何求值, 還是根據本題相同位數連續出現的性質, 按位求.

設 \(k\) 有 \(len\) 位.

對於比 \(k\) 位數少的數, 如果其位數為 \(i (i \leq len)\), 則設 \(k\) 的前 \(i\) 位組成的 \(i\) 位數為 \(k_i\), 所有 \(i\) 位數中, 小於等於 \(k_i\) 的數排在 \(k\) 前面, 大於 \(k_i\) 的數排在 \(k\) 後面.

對於和 \(k\) 相同位數的數, 比 \(k\) 小的數都在 \(k\) 前面, 比 \(k\) 大的數都在 \(k\) 後面.

但是對於 \(k\) 本身也計算進去了, 所以需要再減去 \(1\).

得到 \(min\) 的表示式

\[min = (\sum _^ k_i - 10^ + 1) - 1

\]其中 \(k_i = \frac}\)

所以\[min = (\sum _^ \frac} - 10^ + 1) - 1

\]由於\(k\) 前面的最少有 \(min\) 個數, 所以

\(k < min\), 則答案不存在;

\(k = min\), 則答案就是k;

\(k > min\), 則繼續列舉更高位數的數.

這時, 已經求出 \(min\) 且 \(min > m\), 從 \(len + 1\) 位數開始列舉.

其實和位數小於 \(len\) 的數相似, 但是不同的是, \(k_i\) 此時排在 \(k\) 之後, 可以很簡單地寫出上面表示式中 \(i > len\) 的情況.

\(i\) 位數中排在 \(k\) 前面的數的個數

\[k * 10^ - 10^

\]所以只要列舉位數 \(i\), 求出 \(n\) 的位數 \(len_n\)

(由於最高位數的數大概率取不完, 所以這裡先算能取完的位數 \(len_n - 1\), 之後再算缺少的數)

\[\sum _^\left\

k * 10^ - 10^ + 1\ \ (i < len)\\

k * 10^ - 10^\ \ (i \geq len)

\end

\right\}< m

\]這時的 \(n\) 是 \(k * 10^\) 也就是 \(k\) 後面補 '\(0\)', 直到位數達到 \(len_n - 1\).

設上式所求的 \(k\) 前面的數字有 \(q'\) 個, 距離要求的 \(m\) 個還差 \(m - q'\) 個.

還差的這些數無疑位數是 \(len_n\), 而且一定是從 \(10^\) 開始, 到 \(10^ + m - q' - 1\) 結束, 所以最後的答案是

\[n = 10^ + m - q' - 1

\]

#include #include using namespace std;

long long m, k, ten[20], len(0), min(0);

void getlen(long long x)

return;

}void getmin(long long x)

min--; //去掉 k 本身

return;

}int main()

scanf("%lld%lld", &k, &m);

m--;

getlen(k); //求 len

getmin(k); //求 min

if (min > m)

if (min == m)

register int lenn(len + 1); //因為要列舉 lenn, 所以 lenn 充當迴圈控制變數

while (min < m)

min += k * ten[lenn - len] - ten[lenn - 1];

++lenn;

} --lenn; // lenn 從 lenn + 1 變回 lenn

min -=

k * ten[lenn - len] - ten[lenn - 1]; // min 回到 lenn = lenn - 1 時的情況

printf("%lld\n", ten[lenn - 1] + m - min - 1);

// system("pause"); // vsc使用者常常忘記刪除的一行

return 0;

}

洛谷 P2022 有趣的數

讓我們來考慮1到n的正整數集合。讓我們把集合中的元素按照字典序排列,例如當n 11時,其順序應該為 1,10,11,2,3,4,5,6,7,8,9。定義k在n個數中的位置為q n,k 例如q 11,2 4。現在給出整數k和m,要求找到最小的n,使得q n,k m。輸入輸出格式 輸入檔案只有一行,是兩...

洛谷P2022 有趣的數

題目鏈結 首先求出1 k中有多少個在k前面的數的個數,若 m,則無解 比如12345,從第一位開始,1 0 1 共2個 1 0 1 12 10 12共3個 12 10 1 123 100 123 共24個 123 100 1 1234 1000 1234 共235個 1234 1000 1 之後看還...

洛谷 P2022 有趣的數

我們把乙個數稱為有趣的,當且僅當 它的數字只包含0,1,2,3,且這四個數字都出現過至少一次。所有的0都出現在所有的1之前,而所有的2都出現在所有的3之前。最高位數字不為0。因此,符合我們定義的最小的有趣的數是2013。除此以外,4位的有趣的數還有兩個 2031和2301。請計算恰好有n位的有趣的數...