code forces 1373 E - Sum of Digits 思維分析性質

容易發現:大部分情況下f[x+1]=f[x]+1;

如果全部f[x],滿足這個性質,則直接可以求出f[x]進行構造。

但由於x+k會發生進位,f[x]出現兩個等差數列,中間出現斷層。

且只會出現2個等差數列,因爲k小於等於9,即x最多進位1次。(個位往前進位)

所以我們枚舉個位c,如果k+c<=9,則不會發生進位。直接用等差數列求出f[x]即可。(f[x]+f[x]+1+k)*(k+1)/2 。

然後從個位進行構造,低位儘量取大數,這樣高位可以取少一點,使得整體儘量小。

否則的話再枚舉個位前面9的個數t,(因爲個位發生進位,前面是9的話會發生連環進位)。

進位導致第二個等差數列的首項爲第一個等差數列末項  +1 - 9*(t+1).

然後就可以求出f[x]了。  

構造同上,不過注意滿足後t+1位都是9.然後t+2位不能爲9.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt=1;
void init(){cnt=1,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
ll mi;
int main()
{
	ios::sync_with_stdio(false);
  	cin.tie(0);
	int t;
	cin>>t;
	while(t--)
	{
		mi=2e18;
		int n,k;
		cin>>n>>k;
		bool f=false;
		for(int c=0;c<=9;c++)//枚舉個位
		{
			if(c+k<=9)
			{
				int now=n-(1+k)*k/2;
				if(now%(k+1)==0)
				{
					
					now/=(k+1);
					ll tp=c,b=1;
					now-=c;
					if(now<0)continue;
					while(now>9)
					{
						b*=10;
						tp+=b*9;
						now-=9;
					}
					if(now)b*=10,tp+=b*now;
				//	cout<<c<<"  "<<tp<<"  "<<mi<<endl;
					mi=min(tp,mi);f=true;
				}
				continue;
			}
			for(int t=0;t<=15;t++)//十位之前連續9的個數
			{
				
				int now=n+(t+1)*9*(c+k-9)-(1+k)*k/2;
				
				if(now%(k+1)==0)
				{
					now/=(k+1);
					ll tp=c,b=1;now-=c;
					for(int j=1;j<=t;j++)
					{
						b*=10;
						tp+=b*9;
						now-=9;
					}
					if(now<0)continue;
					if(now>=8)b*=10,tp+=b*8,now-=8;
					while(now>9)
					{
						b*=10;
						tp+=b*9;
						now-=9;
					}
					if(now)b*=10,tp+=b*now;
				//	cout<<c<<"  "<<t<<"   "<<tp<< endl;
					mi=min(mi,tp);f=true;
				}
				//f[x]*(k+1)+(1+k)*k/2-(t+1)*9*(c+k-10)=n
			 } 
		 }
		 if(f)cout<<mi<<endl;
		 else cout<<-1<<endl;
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章