2019牛客多校3 d题补题记

链接:https://ac.nowcoder.com/acm/contest/883/D
来源:牛客网

For little pupils, a very large number usually means an integer with many many digits. Let’s define a class of big integers which consists only of the digit one (11 \cdots 1)(11⋯1). The first few integers in this class are 1, 11, 111, 1111 \cdots1,11,111,1111⋯. Denote \ A(n) A(n) as the \ n n-th smallest integer in this class. To make it even larger, we consider integers in the form of A(a^b)A(a
b
). Now, given a prime number \ p p, how many pairs \ (i, j) (i,j) are there such that 1 \leq i \leq n,\ 1 \leq j \leq m,\ A(i^j) \equiv 0(mod \ p)1≤i≤n, 1≤j≤m, A(i
j
)≡0(mod p).

对于这种连续几个数字的 我们可以转化成 10^x - 1 再乘上几个系数的这种东西来求解
利用欧拉函数的性质 a^phi(n) == 1 (mod n) a,n 需要互质 的情况下 这题需要求出最小的循环节位多少 而最小循环节d肯定是 phi(n) 的约数 所以直接枚举最小的约数并且满足 a^d == 1 (mod n) 这样就好了 因为这个题目是 i^j 那这个怎么考虑呢 因为是幂次 我们就从j开始枚举 对于每一个i 不好筛选除满足条件的j 但是对于每一个j 容易筛选除满足条件的i 这个i一定要包含 d 的所有质因子 并且幂次要比d中的质因子的幂次要大 那么对于这个i来说的话 找到最小的满足条件的g i必须要是g的 倍数 那么在j次幂下 满足条件的个数就有 n/g 个 对于j的处理 发现幂次最多不超过30 超过30的个数就和30的一样了 所以需要处理的就是前 1 ~ 30个;2 ^ 30 > d

#include <bits/stdc++.h>

using namespace std;

const int maxn = 1e5 + 1000;
const long long int inf = 0xfffffffffffffff;
typedef long long ll;
ll mod;
ll qp(ll a,ll b)
{
    ll ans = 1,a0 = a % mod;
    b %= mod;
    while(b)
    {
        if(b & 1) ans = ( (ans % mod) * (a0 % mod) ) % mod;
        b >>= 1;
        a0 = (a0 * a0) % mod;
    }
    return ans % mod;
}

ll get_phi(ll n)
{
    ll ans = n;
    ll m = n;
    for(ll i = 2; i * i <= m; i++)
    {
        if(m % i == 0)
        {
            ans = ans / i * (i - 1);
            while(m % i == 0) m /= i;
        }
    }
    if(m > 1) ans = ans / m * (m - 1);
    return ans;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll p,n,m;
        scanf("%lld%lld%lld",&p,&n,&m);
        if(p == 2 || p == 5)
        {
            puts("0"); continue;
        }
        mod = 9 * p;
        ll phi = get_phi(9 * p);
        ll d = inf;
        for(ll i = 1; i * i <= phi; i++) // 求最小循环节
        {
            if(phi % i == 0)
            {
                if(qp(10,i) == 1)
                {
                    d = min(d,i);
                }
                if(qp(10,phi / i) == 1)
                {
                    d = min(d,phi / i);
                }
            }
        }
        vector<pair<ll,ll> > factor;
        factor.clear();
        // 求d的质因数 还要 质因数的幂次
        for(int i = 2; i * i <= d; i++)
        {
            int cnt = 0;
            while(d % i == 0)
            {
                cnt++;d /= i;
            }
            if(cnt) factor.push_back(make_pair(i,cnt));
        }
        if(d > 1) factor.push_back(make_pair(d,1));
        ll time30 = 0,t_ans = 0;
        for(int j = 1; j <= 30 && j <= m; j++)
        {
            ll g = 1;
            for(int i = 0; i < factor.size(); i++)
            {
                ll p = factor[i].first,pw = factor[i].second;
                ll k = ceil(pw*1.0/j);//pw / j + (pw % j == 0? 0 : 1);
                for(int tt = 0; tt < k; tt++)
                {
                    g *= p;
                }
            }
            t_ans += n / g;
            if(j == 30) time30 = n / g;
        }
        if(m > 30) t_ans += (time30 * (m - 30));
        cout<<t_ans<<endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值