題解:AT_abc382_d [ABC382D] Keep Distance

困死了要發表於2024-12-02

題目傳送門

思路

老樣子,先看資料範圍。

  • \(2 \leq N \leq 12\)
  • \(10N - 9 \leq M \leq 10N\)

加上限時五秒鐘,所以可以放心的寫。


\(X\) 為輸出的倒數第 \(Y\) 個數,\(Z\) 為上一個數的值。
觀察樣例,確定 \(X\) 的取值範圍是 \((Z+10) \sim (M-Y \times 10+10)\) 這樣我們就可以用遞迴來寫這道題了。
按照題目要求,先統計數量。


首先,按照先前求出來的範圍列舉每個位置上的值。
每一個數字至少要比前一個大 10 ,當它統計出來的數字已經大於了它所限制的最大值,就提前返回。
如果它的每一個位置上都填上了值,並且最後一位的值滿足題目搜給的要求,就統計。

void qq1(int x,int y)
{
	if(y>m)
	return ;
	if(x==0)
	{
		s++;
		return ;
	}
	for(int i=y+10;i<=m-x*10+10;i++)
		qq1(x-1,i);
}

然後按照同樣的方法再遞迴一次。
但是如果它的每一個位置上都填上了值,並且最後一位的值滿足題目搜給的要求,不再統計,直接輸出。

void qq(int x,int y)
{
	if(y>m)
	return ;
	if(x==0)
	{
		for(int i=n;i>=1;i--)
		cout<<h[i]<<" ";
		cout<<endl;
		return ;
	}
	for(int i=y+10;i<=m-x*10+10;i++)
	{
		h[x]=i;
		qq(x-1,i);
	}
}

程式碼

#include<bits/stdc++.h>
using namespace std;
int n,m;
int h[20];
int s=0;
void qq1(int x,int y)
{
	if(y>m)
	return ;
	if(x==0)
	{
		s++;
		return ;
	}
	for(int i=y+10;i<=m-x*10+10;i++)
		qq1(x-1,i);
}
void qq(int x,int y)
{
	if(y>m)
	return ;
	if(x==0)
	{
		for(int i=n;i>=1;i--)
		cout<<h[i]<<" ";
		cout<<endl;
		return ;
	}
	for(int i=y+10;i<=m-x*10+10;i++)
	{
		h[x]=i;
		qq(x-1,i);
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(),cout.tie();
	cin>>n>>m;
	qq1(n,-9);
	cout<<s<<endl;
	qq(n,-9);
}

相關文章