【2017 BSUIR Semifinal G】Digital characteristic 题解

题目大意

  定义函数 f ( n ) f(n) f(n) 表示对 n n n 一直求数位和直至 n n n 为个位数,即:
f ( n ) = { n n < 10 , f ( g ( n ) ) otherwise, f(n)=\begin{cases} n&n<10, \\ f(g(n))&\text{otherwise,} \end{cases} f(n)={ nf(g(n))n<10,otherwise,

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

   0 ≤ a , b ≤ 1 0 9 ,    2 ≤ m ≤ 1 0 9 + 7 ,    1 ≤ k ≤ 1 0 9 0 \leq a,b \leq 10^9,~~2 \leq m \leq 10^9+7,~~1 \leq k \leq 10^9 0a,b109,  2m109+7,  1k109
  多测, T ≤ 1 0 4 T \leq 10^4 T104

\\
\\
\\

题解

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

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

  注意到这个式子,是先让 a + b i a+bi a+bi m m m,再求和,模 9 9 9。这样子直接做就不好做,所以要把里面的   m o d     m \bmod~m mod m 变形:
n   m o d   9 = ∑ i = 0 k − 1 ( ( a + b i ) − ⌊ a + b i m ⌋ ⋅ m )   m o d   9 n \bmod 9 =\sum_{i=0}^{k-1}\big((a+bi)-\lfloor \frac{a+bi}{m} \rfloor \cdot m) \bmod 9 nmod9=i=0k1((a+bi)ma+bim)mod9
  这样就变成类欧了。

代码

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

你可能感兴趣的:(算法_数论)