D Big Integer
题意
求有多少对的
i
i
i和
j
j
j使得
A
[
i
j
]
≡
0
A[i^j]\equiv 0
A[ij]≡0(mod p)
1
⩽
i
⩽
n
1\leqslant i\leqslant n
1⩽i⩽n,
1
⩽
j
⩽
m
1\leqslant j\leqslant m
1⩽j⩽m
其中A[n]表示有n位全1的十进制数,如
A
[
5
]
=
11111
A[5]=11111
A[5]=11111
思路
这题相当复杂啊,首先
111
…
…
11
=
1
0
n
−
1
9
111……11=\frac {10^n-1}{9}
111……11=910n−1,原式可化为
1
0
n
≡
1
10^n\equiv1
10n≡1(mod 9p),
当p!=2或5时
g
c
d
(
10
,
9
p
)
=
1
gcd(10,9p)=1
gcd(10,9p)=1,再根据欧拉定理可得
1
0
φ
(
9
p
)
≡
1
10^{φ(9p)}\equiv 1
10φ(9p)≡1(mod 9p)本来化到这里其实就可以继续下一步了,但是因为在后面的计算中用9p会爆longlong,因此还需要继续化简,由于欧拉函数是积性函数,
φ
(
9
p
)
=
φ
(
9
)
∗
φ
(
p
)
=
6
∗
(
p
−
1
)
φ(9p)=φ(9)*φ(p)=6*(p-1)
φ(9p)=φ(9)∗φ(p)=6∗(p−1),由于最小循环节一定在
φ
(
9
p
)
φ(9p)
φ(9p)的因子中取,所以特判一下p=3的情况,然后只需要枚举
φ
(
p
)
φ(p)
φ(p)的因子就好了。
网上搜的题解说 若有 n 对 1 0 n ≡ 1 ( m o d 9 p ) 10 n ≡ 1 ( m o d 9 p ) 10^n \equiv 1\pmod {9p}10 n≡1(mod9p) 10n≡1(mod9p)10n≡1(mod9p)成立, 那么一定有 1 0 n ≡ 1 ( m o d p ) 10 n ≡ 1 ( m o d p ) 10^n\equiv 1\pmod {p}10 n ≡1(modp) 10n≡1(modp)10n≡1(modp)成立,不是很懂这是什么定理
这样求得了最小循环节d,原题就转化为:有多少对的i,j使得 i j ≡ 0 i^j\equiv 0 ij≡0(mod d)
把 d 质因数分解:
d
=
p
1
k
1
p
2
k
2
⋯
p
l
k
l
d=p_1^{k_1}p_2^{k_2}\cdots p_l^{k_l}
d=p1k1p2k2⋯plkl, 要使得
i
j
i^j
ij 是
d
d
d 的倍数,那么在
i
j
i^j
ij 的质因数分解中
p
1
,
p
2
⋯
p
l
p_1,p_2\cdots p_l
p1,p2⋯pl 的指数中都要比
d
d
d 中的大,所以我们考虑 j 固定的时候,有多少个 i 可以满足条件。
i
i
i 必须是
g
=
p
1
⌈
k
1
j
⌉
p
2
⌈
k
2
j
⌉
⋯
p
l
⌈
k
l
j
⌉
g = p_1^{\lceil {k_1\over j} \rceil} p_2^{\lceil {k_2\over j} \rceil}\cdots p_l^{\lceil {k_l\over j} \rceil}
g=p1⌈jk1⌉p2⌈jk2⌉⋯pl⌈jkl⌉ 的倍数,(至于为什么上取整,可以想一想,因为要求最小的
x
x
x, 有
x
∗
j
>
=
k
1
&
&
x
∗
(
j
−
1
)
<
k
1
x*j >= k_1 \&\& x*(j-1) < k_1
x∗j>=k1&&x∗(j−1)<k1 。因此一共有
n
g
n\over g
gn个合法的
i
i
i。
由于k最大不超过30,枚举j时只要枚举到30,大于30的解跟30的情况是一样的
代码
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <bitset>
#include <cctype>
#include <cstdio>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iomanip>
#include <numeric>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
//const int mod = 998244353;
const int maxn = 1e5+20;
ll p;
int n,m;
ll fac[maxn],num[maxn];
int cnt;
ll qmod(ll a,ll b,ll mod)
{
ll c=1;
while(b)
{
if(b&1)
{
c=c*a%mod;
}
a=a*a%mod;
b>>=1;
}
return c;
}
ll getfac(ll x) //质因子分解
{
cnt=0;
memset(fac,0,sizeof(fac));
memset(num,0,sizeof(num));
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
fac[++cnt]=i;
while(x%i==0)
{ ll p,n,m;
num[cnt]++;
x/=i;
}
}
}
if(x>1)
{
fac[++cnt]=x;
num[cnt]++;
}
}
int main(){
int t;
cin>>t;
while(t--)
{
ll d;
cin>>p>>n>>m;
if(p==2||p==5)
{
printf("0\n");
continue;
}
else if(p==3)
{
d=3;
}
else{
d=p-1;
getfac(d);
for(int i=1;i<=cnt;i++)
{
for(int j=0;j<num[i];j++)
{
if(qmod(10,d/fac[i],p)==1)
d/=fac[i];
}
}
}
getfac(d); //分解d
ll g;
ll ans=0;
for(int i=1;i<=min(30,m);i++)
{
g=1;
for(int j=1;j<=cnt;j++)
{
int ma=(num[j]%i==0?num[j]/i:num[j]/i+1);
for(int k=1;k<=ma;k++)
{
g*=fac[j];
}
}
ans+=n/g;
}
if(m>30)
ans+=n/g*(m-30);
printf("%lld\n",ans);
}
}