题意:
用 $A(n)$ 表示第 $n$ 个只由1组成分整数,现给定一个素数 $p$,求满足 $1 leq ileq n, 1 leq j leq m, A(i^j) equiv 0(mod p)$ 的 $(i, j)$ 对数。
分析:
$11...11 = frac{10^n-1}{9} equiv 0(mod p)$ 等价于 $10^n equiv 1(mod 9p)$,当 $p eq 2,5$ 时,有 $gcd(10, 9p)=1$,因此 $10^{phi(9p)} equiv 1(mod 9p)$。我们需要找到满足等式最小的数 $d$,也是循环节,显然 $d | phi (9p)$,直接枚举 $phi(9p)$ 的约数验证即可。
找到循环节 $d$ 后,我们需要知道有多少对 $(i, j)$ 满足 $d | i^j$.
对 $d$ 做质因数分解, $d = p_1^{k_1}p_2^{k_2}...p_l^{k_l}$,考虑 $j$ 固定的时候,$i$ 需要满足什么条件?$i$ 必须是 $g = p_1^{left lceil frac{K_1}{j} ight ceil} p_2^{left lceil frac{K_2}{j} ight ceil} ... p_l^{left lceil frac{K_l}{j} ight ceil}$ 的倍数,因此共有 $frac{n}{g}$ 个合法的 $i$。
由于 $k_i leq 30$,所以 $j$ 增加到30以上和 $j=30$ 的结果是一样的,枚举 $j$ 从1到30,分别计算 $g$ 即可。
当 $p=2,5$ 的时候,显然答案为0.
$phi(9p)$ 也不必用欧拉函数计算,当 $p eq 3$ 时,3与p互素,根据欧拉函数的积性,$phi (9p) = phi (9)phi (p) = 6(p-1)$.
由于快速幂会爆long long,需要用__int128(血的教训啊,wa了好多发,枯了)
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll p, m ,n; map<ll, ll>ma; __int128 qpow(__int128 a, __int128 b, __int128 p) { __int128 res = 1; while(b) { if(b & 1) res = res * a % p; a = (a * a) % p; //a*a会爆long long b >>= 1; } return res; } ll qpow2(ll a, ll b) { ll res = 1; while(b) { if(b & 1) res = res * a; a = a * a; b >>= 1; } return res; } //约数枚举O(√n) ll divisor(ll n, ll p) { vector<ll>res; for (ll i = 1; i * i <= n; i++) { if (n % i == 0) { //printf("i:%lld ", i); if(qpow(10, i, 9*p) % (9*p) == 1) return i; if(i != n / i) res.push_back(n / i); } } for(ll i = res.size()-1;i >= 0;i--) { // printf("i:%lld ", res[i]); if(qpow(10, res[i], 9*p) % (9*p) == 1) return res[i]; } return 0; } //整数分解O(√n) void prime_factor(ll n) { for (int i = 2; i * i<= n; i++) { while (n % i == 0) { ++ma[i]; n /= i; } } if (n != 1) ma[n] = 1; //最多只有一个素因数大于√n } //j固定的情况下的对数 ll OneJ(int j) { ll res = 1; for(auto it = ma.begin();it != ma.end();it++) { res *= qpow2((*it).first, (ll)ceil((*it).second * 1.0 / j)); } return n / res; } int main() { int T; scanf("%d", &T); while(T--) { scanf("%lld%lld%lld", &p, &n, &m); //int fai = euler_phi(9*p); ll k; if(p == 2 || p == 5) { printf("0 "); continue; } if(p == 3) { k = divisor(18, p); } else k = divisor(6*(p-1), p); //printf("k:%lld ", k); if(k == 0) printf("0 "); else { ma.clear(); ll res = 0; prime_factor(k); //printf("k:%lld ", k); if(m < 30) { for(int i = 1;i <= m;i++) res += OneJ(i); } else { for(int i = 1;i <= 29;i++) res += OneJ(i); int tmp = OneJ(30); res += tmp * (m - 29); } printf("%lld ", res); } } return 0; }