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 
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<=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<

 

你可能感兴趣的:(CF,技巧思维题)