CF1242D. Number Discovery

题目大意


题解

神仙题

直接在原序列上不好搞,考虑按照值顺序考虑,设直接加的为一类数,求和加进去的为二类数

有一个牛比结论:\([i(k^2+1)+1,(i+1)(k^2+1)]\)中存在恰好一个二类数(i从0开始)

先假设这个是对的,当前已知第i段的数为x,考虑求第ki+t段的x',初始段为0目标段为(n-1)/(k^2+1),初始x为k(k+1)/2

\(x'=\sum_{j=1}^i i(k^2+1)+kt+j+[...>=x]\)

因为每段长为k^2+1,所以会在后面产生恰好k个二类数,由于不知道前面的二类数所以只考虑本段产生的

展开得到\(x'=ik(k^2+1)+k^2t+k(k+1)/2+(0\text{~}k)\)

考虑第ki+t段的范围,发现当k>=2时即使后面的0~t是最坏情况也刚好在范围内,所以不展开了(

于是可以算出x',后面的考虑区间与x的关系可以求出

最后根据n和x的大小关系讨论即可O(log)求解

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define ll long long
//#define file
using namespace std;

int a[101],T,i,j,k,l,tot;
ll s,n,K,x,I,ans;

void turn(ll t) {x=I*K*(K*K+1)+K*K*t+(1+K)*K/2+max(I*(K*K+1)+K*t+K-max(x,I*(K*K+1)+K*t+1)+1,0);}

int main()
{
	#ifdef file
	freopen("CF1242D.in","r",stdin);
	#endif
	
	scanf("%d",&T);
	for (;T;--T)
	{
		scanf("%lld%lld",&n,&K),s=(n-1)/(K*K+1);
		x=s,tot=0;
		while (x) a[++tot]=x%K,x/=K;
		
		I=0,x=K*(K+1)/2;
		fd(i,tot,1)
		turn(a[i]),I=I*K+a[i];
		if (n==x)
		ans=(s+1)*(K+1);
		else
		ans=n-s-(n>=x)+(n-s-(n>=x)-1)/K;
		printf("%lld\n",ans);
	}
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}
posted @ 2020-10-13 20:30  gmh77  阅读(134)  评论(0编辑  收藏  举报