【CodeForces 468C】Hack it!

链接:

洛谷

博客园

题目大意:

(f(x)) 表示 (x) 的各个数位之和。

给定一个正整数 (a),请您找到 (l,r) 满足 (sumlimits_{i=l}^r f(i)equiv0pmod{a})

(1leq l,rleq 10^{200})(1leq aleq10^{18})

正文:

是道神仙题。首先有一个显而易见的性质:当 (f(x)=x) 时,(f(x+10^{18})=x+1)(这里加上 (10^{18}) 是因为这是 (a) 的上界)。

那么当 (sumlimits_{i=0}^{10^{18}-1}f(i)equiv xpmod{a}),则有:

[sumlimits_{i=1}^{10^{18}}f(i)equiv x+1pmod{a} ]

以此类推得到:

[sumlimits_{i=a-x}^{10^{18}-1+a-x}f(i)equiv x+a-xequiv 0pmod{a} ]

所以我们可以得到一组 ([a-x,10^{18}-1+a-x]) 的解。接下来的问题就可以转化到如何求 (sumlimits_{i=0}^{10^{18}-1}f(i)) 了。


然后根据初赛知识,这个玩意可以递归求得。

先设函数 (F(x)=sum_{i=0}^{10^x-1}f(i)),它可以这么递归:

[F(x)=left{egin{matrix} 45&(x=1)\ 45 imes10^{x-1}+10F(x-1)&(x>1) end{matrix} ight.]

然后就可以暴力实现了:

ll qpow(ll a, int b)
{
	ll ans = 1;
	for (; b; a *= a, b >>= 1)
		if(b & 1) ans *= a;
	return ans;
}

ll F(int x)
{
	return x == 1? 45ll: 45ll * qpow(10, x - 1) + 10ll * F(x - 1);
}

int main()
{
	printf ("%lld
", F(17));
	return 0;
}

这里直接算 (F(18)) 会溢出,所以先算出 (F(17)=7.65 imes10^{18}),然后用电脑上自带的计算器得到 (F(18)=8.1 imes 10^{19})。于是便得到了答案。

代码:

ll n, inf = 1e18;

int main()
{
	scanf ("%lld", &n);
	ll l = n - inf % n * 9 % n * 9 % n, r = inf + l - 1; //注意这里直接乘81会溢出,所以乘两遍9。
	printf ("%lld %lld
", l, r);
	return 0;
}
原文地址:https://www.cnblogs.com/GJY-JURUO/p/14539563.html