赛中花了四小时搞这题没搞出来,结果赛后发现\(p=3\)的特判写错了,哭哭
\(A(i^j)=\sum_{k=0}^{i^j-1}10^k=\frac{10^{i^j}-1}{9}\equiv0(mod\ p)\)
当\(p \neq3\)时(划重点①!!!),有\(10^{i^j}\equiv1(mod\ p)\)
考虑到费马小定理,当\(gcd(10, p)=1\)时,即\(p \neq 2\)且\(p\neq5\)时(划重点②!!!),有\(10^{i^j-(p-1)}\equiv10^{i^j-k(p-1)}\equiv...\equiv10^{i^j\%(p-1)}\equiv1\equiv10^0(mod\ p)\)
所以\(p-1\ | \ i^j\).
但是\(p-1\)不一定是使\(10^x\equiv1(mod\ p)\)的最小正整数\(x\),所以我们设\(q\)是这个最小的\(x\),使\(10^q\equiv1(mod\ p)\)
显然我们有\(q\ |\ p-1\),所以有\(q\ |\ i^j\).
这个\(q\)可以\(O(\sqrt{p}log_2p)\)的时间复杂度暴力求出。
接下来的问题就转化为了有多少对\(1 \leq i \leq n, 1\leq j\leq m\)使得\(q\ |\ i^j\).
考虑\(q\)的质因数分解式\(q=p_1^{e_1}p_2^{e_2}...p_x^{e_x}\),我们设集合\(P_q=\{p_1,p_2,...,p_x\}\)
再考虑\(i\)的质因数分解式\(i=r_1^{d_1}r_2^{d_2}...r_y^{d_y}\),集合\(P_i=\{r_1,r_2,...,r_y\}\),显然只有当\(P_i \supset P_q\)时,才有可能有\(q\ |\ i^j\).
方便起见,改写\(i\)的分解式\(i=p_1^{d_1}p_2^{d_2}...p_x^{d_x}p_{x+1}^{d_{x+1}}...p_y^{d_y}\).
现在考虑这样一个问题:我们固定\(i\),有多少个\(j\)满足条件?
显然,\(\forall k \leq x,\)有\(jd_k\geq e_k\),所以\(j\geq \lceil\frac{e_k}{d_k}\rceil\),所以满足条件的\(j\)有\(m-{max}_{k=1}^x\lceil\frac{e_k}{d_k}\rceil+1\)个。
因此枚举\(i\)去算\(j\)的总最坏复杂度降到了\(O(nlogn)\)(?)
接下来我们枚举\(p_1,p_2,...,p_x\)的指数\(d_1,d_2,...,d_x\),考虑有多少个\(1\leq i \leq n\)使得它的质因数分解式\(i=p_1^{f_1}p_2^{f_2}...p_x^{f_x}p_{x+1}^{f_{x+1}}...p_y^{f_y}\)中\(d_1=f_1,d_2=f_2,...,d_x=f_x\).
这个可以容斥来做,容易求出\(f_1\geq d_1,f_2\geq d_2,...,f_x\geq d_x\)的\(i\)的个数为\(\lfloor\frac{n}{p_1^{d_1}p_2^{d_2}...p_x^{d_x}}\rfloor\)
容斥地加加减减\(f_k\geq d_k+1\)的\(i\)的个数,就能算出最后结果。
复杂度?我不会算,但是因为\(p\)不会超过8个,所以目测\(O(\)能过\()\)......我只跑了12ms......
总复杂度\(O(\sqrt plog_2p+\)能过\()\).(???)
#include <bits/stdc++.h>
#define LL long long
#define MAXN 100008
using namespace std;
LL p, n, m;
LL q;
LL qp(LL a, LL b, LL mod)
{
LL ret = 1;
while (b)
{
if (b & 1)
ret = ret * a % mod;
a = a * a % mod;
b >>= 1;
}
return ret;
}
LL prime[18], ans;
int e[18];
int primelen = 0;
int d[18];
LL getval(LL msk, LL prod)
{
int cnt1 = 0;
for (int i = 0; i < primelen; ++i)
{
if (msk & (1 << i))
{
cnt1++;
prod *= prime[i + 1];
if (prod > n)
return 0;
}
}
if (cnt1 % 2)
return - (n / prod);
else
return n / prod;
}
void dfs(int d[], int i, LL prod)
{
if (prod > n)
return;
if (i > primelen)
{
LL ret = 0;
for (int msk = 0; msk < (1 << primelen); ++msk)
{
ret += getval(msk, prod);
}
//cout << "ret = " << ret << endl;
int mx = -1;
for (int j = 1; j <= primelen; ++j)
{
mx = max(mx, (int)ceil(e[j] * 1.0 / d[j]));
}
//cout << "mx = " << mx << endl;
ans += max(0LL, m - mx + 1) * ret;
return;
}
LL cprod = prod;
for (d[i] = 1; cprod * prime[i] <= n; ++d[i])
{
cprod *= prime[i];
dfs(d, i + 1, cprod);
}
return;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
ans = 0;
memset(prime, 0, sizeof(prime));
memset(d, 0, sizeof(d));
memset(e, 0, sizeof(e));
primelen = 0;
q = 0x3f3f3f3f;
scanf("%lld %lld %lld", &p, &n, &m);
for (LL i = 1; i * i <= p - 1; ++i)
{
if ((p - 1) % i)
continue;
if (qp(10, i, p) == 1)
q = min(q, i);
if (qp(10, (p - 1) / i, p) == 1)
q = min(q, (p - 1) / i);
}
//cout << "q = " << q << endl;
LL temp = q;
for (int i = 2; i * i <= temp; ++i)
{
if (temp % i == 0)
{
prime[++primelen] = i;
while (temp % i == 0)
{
temp /= i;
e[primelen]++;
}
}
}
if (temp > 1)
{
prime[++primelen] = temp;
temp = 1;
e[primelen] = 1;
}
dfs(d + 1, 1, 1);
if (p == 2 || p == 5 || q >= 0x3f3f3f3f)
ans = 0;
else if (p == 3)
ans = (n / 3) * m;
printf("%lld\n", ans);
}
}