2019牛客多校第三场D BigInteger——基础数论

题意:

用  $A(n)$ 表示第 $n$ 个只由1组成分整数,现给定一个素数 $p$,求满足 $1 \leq i\leq 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 \neq 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} \right \rceil} p_2^{\left \lceil \frac{K_2}{j} \right \rceil} ... \ p_l^{\left \lceil \frac{K_l}{j} \right \rceil}$ 的倍数,因此共有 $\frac{n}{g}$ 个合法的 $i$。

由于 $k_i \leq 30$,所以 $j$ 增加到30以上和 $j=30$ 的结果是一样的,枚举 $j$ 从1到30,分别计算 $g$ 即可。

当 $p=2,5$ 的时候,显然答案为0.

$\phi(9p)$ 也不必用欧拉函数计算,当 $p \neq 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\n", 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\n", 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\n");
            continue;
        }

        if(p == 3)
        {
            k =  divisor(18, p);
        }
        else  k = divisor(6*(p-1), p);  //printf("k:%lld\n", k);

        if(k == 0)  printf("0\n");
        else
        {   ma.clear();
            ll res = 0;
            prime_factor(k);  //printf("k:%lld\n", 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\n", res);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lfri/p/11258814.html