题目链接:
题意:有这样一些数,全部由1组成,例如:1,11,111,1111,…
定义A(n)为第n大的数,计算: ∑ i = 1 n ∑ j = 1 m [ A ( i j ) ≡ 0 ( m o d p ) ] \sum_{i=1}^{n}\sum_{j=1}^{m}[A(i^j)\equiv 0 ( mod p)] ∑i=1n∑j=1m[A(ij)≡0(modp)]
我们设:
A
(
n
)
=
1
0
n
−
1
9
A(n)=\frac{10^n-1}{9}
A(n)=910n−1
即:
考虑p与9互质。
(
1
0
n
−
1
)
∗
i
n
v
9
≡
0
(
m
o
d
p
)
(10^n-1)*inv9 \equiv 0(modp)
(10n−1)∗inv9≡0(modp)
因为inv9不为0,故:
1
0
n
≡
1
(
m
o
d
p
)
10^n\equiv 1(mod p)
10n≡1(modp)
由费马小定理,可得n为p-1,也就是存在一个循环节d,使得只要满足
d
∣
i
j
d|i^j
d∣ij,此
i
j
i^j
ij就满足条件。
但这里的循环节不一定是p-1,它可能更小,我们可以通过打表看出。或者我们可以这样想,假设存在p-1的因子d,满足
1
0
d
≡
1
(
m
o
d
p
)
10^d\equiv1(mod p)
10d≡1(modp),此时d就为更小的循环节,那么现在我们只需先找到p-1的循环节。
循环找出来后,就变成求:
∑
i
=
1
n
∑
j
=
1
m
d
∣
i
j
\begin{aligned}\sum_{i=1}^{n}\sum_{j=1}^{m}d|i^j\end{aligned}
i=1∑nj=1∑md∣ij
下面参考官方题解:
设
m
a
=
m
a
x
(
k
1
,
k
2
,
.
.
.
,
k
l
)
ma=max(k_1,k_2,...,k_l)
ma=max(k1,k2,...,kl),那么当
j
>
=
m
a
j>=ma
j>=ma时,g此时都不会再改变,此时就有
n
g
∗
(
m
−
m
a
)
\frac{n}{g}*(m-ma)
gn∗(m−ma)。
再者,当p为2,5时,
1
0
n
≡
0
(
m
o
d
p
)
10^n\equiv 0(mod p)
10n≡0(modp),说明不存在这样的
A
(
i
j
)
A(i^j)
A(ij)
当p=3时,因为p与9并不互质,故题目就变成了求:
∑
i
=
1
n
∑
j
=
1
m
[
A
(
i
j
)
m
o
d
3
=
=
0
]
\sum_{i=1}^{n}\sum_{j=1}^{m}[A(i^j)mod 3==0]
∑i=1n∑j=1m[A(ij)mod3==0],那么显然就变成A(i^j)数字中,各位数相加是否为3的倍数,我们先不考虑j,即有
n
3
\frac{n}{3}
3n这么多个i,那么最后结果就为
n
3
∗
m
\frac{n}{3}*m
3n∗m
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL mod;
LL fast(LL x,LL y)
{
LL ans=1;
while(y)
{
if(y&1) ans=ans*x%mod;
x=x*x%mod;
y>>=1;
}
return ans;
}
pair<LL,LL> pri[2000];
int main()
{
int ncase;
scanf("%d",&ncase);
while(ncase--)
{
LL p,n,m;
scanf("%lld%lld%lld",&p,&n,&m);
mod=p;
if(p==2||p==5){
puts("0");
continue;
}
if(p==3){
printf("%lld\n",n/3*m);
continue;
}
LL mi=p-1,x=p-1;
///找出循环节mi
for(LL i=2;i*i<=x;i++)
{
if(x%i==0){
if(fast(10,i)==1){
mi=min(mi,i);
}
if(fast(10,x/i)==1) mi=min(mi,x/i);
}
}
// printf("mi=%lld\n",mi);
int cnt=0;
x=mi;
LL ma=0;
for(LL i=2;i*i<=x;i++)///质因子分解循环节mi
{
if(x%i==0){
pri[++cnt].second=0;
pri[cnt].first=i;
while(x%i==0){
pri[cnt].second++;
x/=i;
}
ma=max(ma,pri[cnt].second);
}
}
if(x>1){
pri[++cnt].first=x;
pri[cnt].second=1;
ma=max(ma,pri[cnt].second);
}
LL ans=0;
LL g=1;
for(LL j=1;j<=min(m,ma);j++){ ///枚举j
g=1;
for(int i=1;i<=cnt;i++){
g=g*fast(pri[i].first,ceil(1.0*pri[i].second/j));
}
ans+=n/g;
}
if(m>ma){
ans+=(n/g)*(m-ma);
}
printf("%lld\n",ans);
}
return 0;
}