【2017 BSUIR Semifinal G】Digital characteristic 题解

题目大意

  定义函数 f(n)f(n) 表示对 nn 一直求数位和直至 nn 为个位数,即:

f(n)={nn<10,f(g(n))otherwise,f(n)=\begin{cases} n&n<10, \\ f(g(n))&\text{otherwise,} \end{cases}

  其中 g(n)g(n) 表示 nn 的数位和。
  现在有一个很大的 nn,你要求 f(n)f(n)
  这个 nn 是根据四个参数 a,b,m,ka,b,m,k 生成的,首先生成 kk 个数 a,a+b,a+2b,,a+(k1)ba,a+b,a+2b,\cdots,a+(k-1)b(都在 mod m\bmod~m 意义下),然后把它们从后往前拼起来,就是 nn。比如,a=42,b=42,m=2018,k=18a=42,b=42,m=2018,k=18,会生成 n=7567146726305885465044624203783362942522101681268442n=7567146726305885465044624203783362942522101681268442

  0a,b109, 2m109+7, 1k1090 \leq a,b \leq 10^9,\ 2 \leq m \leq 10^9+7,\ 1 \leq k \leq 10^9
  多测,T104T \leq 10^4

题解

  数论技巧什么的。。还是要时常复习啊。。

  首先这个 ff 是有通项公式的,当 n>0n>0f(n)=(n1)mod9+1f(n)=(n-1) \bmod 9+1,也即 f(n)=(n%9==0) ?9 :n%9
  所以我们就是要求 nmod9n \bmod 9 的值。(特判 n=0n=0
  注意到 x>0,10xmod9=1\forall x>0,10^x \bmod 9=1,因此对于 nn 来说,多个数拼起来 mod9\bmod 9 等价于拆开来 mod9\bmod 9 再求和,即 nmod9=i=0k1((a+bi)modm)mod9n \bmod 9 =\sum_{i=0}^{k-1}\big((a+bi) \bmod m \big) \bmod 9

  注意到这个式子,是先让 a+bia+bimm,再求和,模 99。这样子直接做就不好做,所以要把里面的 mod m\bmod~m 变形:

nmod9=i=0k1((a+bi)a+bimm)mod9n \bmod 9 =\sum_{i=0}^{k-1}\big((a+bi)-\lfloor \frac{a+bi}{m} \rfloor \cdot m) \bmod 9

  这样就变成类欧了。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include<bits/stdc++.h>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;

typedef long long LL;

LL a,b,m,k;

LL f(LL a,LL b,LL c,LL n)
{
if (!a) return (n+1)*(b/c)%9;
if (a>=c || b>=c)
{
LL sqr=(n&1) ?(n+1)/2*n :n/2*(n+1) ;
sqr%=9;
return (f(a%c,b%c,c,n)+(a/c)*sqr+(n+1)*(b/c))%9;
} else
{
LL m=(a*n+b)/c;
return (m%9*n%9-f(c,c-b-1,a,m-1)+9)%9;
}
}

int T;
int main()
{
scanf("%d",&T);
while (T--)
{
scanf("%lld %lld %lld %lld",&a,&b,&m,&k);
a%=m, b%=m;
if (a==0 && (k==1 || k>1 && b==0)) {puts("0"); continue;}

int ans=((a*k%9+k*(k-1)/2%9*b%9)%9-m*f(b,a,m,k-1)%9+9)%9;

printf("%d\n",(ans==0) ?9 :ans);
}
}