P11059 [入門賽 #27] 數字 (Hard Ver.)題解

badn發表於2024-10-06

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. 在最高位先放數字1維持\(x\)合法並是\(p\)減1。
  2. 再從最低位開始放數字,當\(p>=9\)時該位放9且讓\(p\)減去9,當\(1\le p\le8\)且不為最高位時使該位為p,接著走向較高的下一位。
  3. 放置過程中若\(p=0\),那麼說明所有數字放完,退出。
  4. 若在最高位仍有\(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;
}

相關文章