专栏文章

题解:AT_abc428_d [ABC428D] 183184

AT_abc428_d题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minkeybq
此快照首次捕获于
2025/12/02 03:51
3 个月前
此快照最后确认于
2025/12/02 03:51
3 个月前
查看原文

AT_abc428_d [ABC428D] 183184

小清新思维题。

Solution

看到这个题一般都会想到去枚举完全平方数,然而 f(C,C+x)f(C,C+x) 最大可以达到 2×10182\times 10^{18} 量级,不可行。
我们不妨换一个思路,注意到在钦定了 C+xC+x 的位数 kk 的前提下,f(C,C+x)f(C,C+x) 能表示的是一个连续的范围。设 L,RL,R 分别为这个范围的上界和下界,则有: L=max(C×10k+10k1,C×10k+C+1)L=\max(C\times 10^k+10^{k-1},C\times 10^k+C+1) R=min[(C+1)×10k1,C×10k+C+D]R=\min[(C+1)\times 10^k-1,C\times 10^k+C+D] LL 需要和 C×10k+10k1C\times 10^k+10^{k-1}max\max 是因为 C+xC+x 的位数必须为 kk,不能有前导零。
易证对于一段连续的区间 L,RL,R,若 l2,r2 (l,r0)l^2,r^2\ (l,r\ge0) 都在这段区间内,则对任意 lirl\le i\le ri2i^2 都在这段区间内。令 l,rl,r 分别为能使它的平方被区间包含的最小值/最大值,则有: l=L,r=Rl=\left \lceil \sqrt{L} \right \rceil,r=\left \lfloor \sqrt{R} \right \rfloor
枚举 kk,累加 rl+1r-l+1
注意可能需要额外注意数据溢出的问题。

Code

CPP
#include<bits/stdc++.h>
#define int long long
#define ull unsigned int
using namespace std;
const int N = 200005;
ull t,c,d;
ull pw[N];
int p10(ull a)
{
	int ret = 0;
	while (a) ret++,a /= 10;
	return ret;
}
signed main()
{
	ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	pw[0] = 1;
	for (int i = 1; i <= 18; i++)
		pw[i] = pw[i-1]*10;
	cin >> t;
	while (t--)
	{
		cin >> c >> d;
		int ans = 0;
		for (int i = p10(c+1); i; i++)
		{
			ull l = c*pw[i]+max(pw[i-1],c+1),r = min((c+1)*pw[i]-1,c*pw[i]+c+d);
			if (l > r) break;
			ull beg = (int)sqrtl(l-1)+1,las = sqrtl(r);
			if (beg > las) continue;
			ans += las-beg+1;
			if (p10(r) >= 19) break;
		}
		cout << ans << '\n';
	}
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...