专栏文章

P12397 「FAOI-R9」函数大师 题解

P12397题解参与者 2已保存评论 1

文章操作

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

当前评论
1 条
当前快照
1 份
快照标识符
@mipfpzj0
此快照首次捕获于
2025/12/03 11:15
3 个月前
此快照最后确认于
2025/12/03 11:15
3 个月前
查看原文
场切了。

Statement

我们定义:
  • s(x)s(x)xx 在十进制下各个数位上的数之和,即 s(x)=i=0(x10imod  10)s(x)=\sum\limits_{i=0}^\infty\left(\left\lfloor \dfrac{x}{10^i} \right\rfloor \mathrm{mod}\;10\right)
  • Sk(x)={xk=0s(Sk1(x))k1S_k(x)=\begin{cases} x & k=0 \\ s(S_{k-1}(x)) & k \ge 1 \end{cases}
  • fk(x)=i=0kSi(x)f_k(x)=\sum\limits_{i=0}^k S_i(x)
给定 kktt 次询问,每次给定 mm,求 y=fk(x)y=f_k(x)y=my=m 的图象的公共点个数。
数据范围:1t1051 \le t \le 10^50k1090 \le k \le 10^91m10181 \le m \le 10^{18}

Analysis

根据 Subtask 提示,分几种情况考虑:
  • k=0k=0 时:
    • 由题意知 f0(x)=x=mf_0(x)=x=m
    • 答案显然为 11
  • k=1k=1 时:
    • 由题意知 f1(x)=x+s(x)=mf_1(x)=x+s(x)=m
    • 由于 xx 可能很大,枚举 xx 无法接受,故考虑枚举较小的 s(x)s(x)
    • 具体地,枚举 a[1,162]a \in [1,162],则 x=max=m-a
    • 验证 s(x)=as(x)=a 是否成立即可。
  • k=2k=2 时:
    • 由题意知 f2(x)=x+s(x)+s(s(x))=mf_2(x)=x+s(x)+s(s(x))=m
    • 类似地,枚举 a[1,162]a \in [1,162],记 b=s(a)b=s(a),则 x=mabx=m-a-b
    • 验证 s(x)=as(x)=as(s(x))=bs(s(x))=b 是否成立即可。
  • k3k \ge 3 时:
    • 由题意知 fk(x)=x+s(x)+s(s(x))++Sk(x)=mf_k(x)=x+s(x)+s(s(x))+\dots+S_k(x)=m
    • 注意到,当 kk 逐渐增大时,Sk(x)S_k(x) 减小极快。
    • 实际上,对于任意 xm1018x \le m \le 10^{18},当 k3k \ge 3 时,Sk(x)S_k(x) 都是相同的。
    • 因此,枚举 a[1,162]a \in [1,162],记 b=s(a)b=s(a)c=s(b)c=s(b),则 x=mab(k2)×cx=m-a-b-(k-2) \times c
    • 验证 s(x)=as(x)=as(s(x))=bs(s(x))=bs(s(s(x)))=cs(s(s(x)))=c 是否成立即可。
复杂度是常数级的。

Code

CPP
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
int t, k;
int s(int x){
	int ret = 0;
	while (x > 0){
		ret += x % 10;
		x /= 10;
	}
	return ret;
}
void solve(){
	int m;
	cin >> m;
	int cnt = 0;
	if (k == 0){ //不要忘记 k=0 的情况
		cout << 1 << endl;
		return;
	}
	for (int a = 0;a <= 200;a++){
		int b = s(a), c = s(b), d = s(c);
		if (k == 1){
			int x = m - a;
			cnt += (s(x) == a);
		}
		else if (k == 2){
			int x = m - a - b;
			cnt += (s(x) == a && s(s(x)) == b);
		}
		else{
			int x = m - a - b - c * (k - 2);
			cnt += (s(x) == a && s(s(x)) == b && s(s(s(x))) == c);
		}
	}
	cout << cnt << endl;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> t >> k;
	while (t--) solve();
	return 0;
}

评论

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

正在加载评论...