【2017 BSUIR Semifinal G】Digital characteristic 题解

题目大意

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

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

  $0 \leq a,b \leq 10^9,\ 2 \leq m \leq 10^9+7,\ 1 \leq k \leq 10^9$
  多测,$T \leq 10^4$

题解

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

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

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

  这样就变成类欧了。

代码

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);
}
}