Solution
先讀題:
在給定x的位數\(n\)和模數\(p\)後,要求構造一個\(x\)在滿足\(x\mod p\)的餘數儘可能小的前提下使\(x\)的數字儘可能小。
我們假設\(x\)的各位數字之和為\(m\),有\(1\le m\le 9n\)。.
(當\(x\)僅在最高位有1時\(m=1\),稱為情況一,當x每位為9時\(m=9n\),稱為情況二)
此時對於\(m\)有兩種情況:
在\(p> 9n\)或\(p=1\)時無需構造,屬於情況一。
\(1<p\le9n\)時需構造,屬於情況二,且可以簡單證明必定有一個合法\(x\)使\(x\mod p=0\)。
做法:
對於情況二,容易想到一種貪心解法,此時的模數\(p\)可直接看作能在每一位放的所有數字之和,步驟如下:
- 在最高位先放數字1維持\(x\)合法並是\(p\)減1。
- 再從最低位開始放數字,當\(p>=9\)時該位放9且讓\(p\)減去9,當\(1\le p\le8\)且不為最高位時使該位為p,接著走向較高的下一位。
- 放置過程中若\(p=0\),那麼說明所有數字放完,退出。
- 若在最高位仍有\(p>0\),那麼時最高位為\(p+1\)(在步驟一中最高位已經放了1,再加上此時的\(p\))並退出。
複雜度分析:
因為按位放數字,有\(n\)位,複雜度為\(O(n)\),且\(1\le n\le 10^{6}\),該方式可行。
Code
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+1;
int n,p,a[N],idx=1;
int main() {
cin>>n>>p;
if(n*9<p){
putchar('1');
for(int i=1;i<n;++i)putchar('0');
}else{
p--;
while(idx!=n&&p){
if(p>=10)a[idx]=9;
else a[idx]=p;
p-=a[idx];
++idx;
}
a[n]=++p;
for(int i=n;i>=1;--i)cout<<a[i];
}
return 0;
}