2019牛客多校第三场 D-Big Integer(数论)

题目链接: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 (111 ···1). The first few integers in this class are 1, 11, 111, 1111 ……. Denote A(n) as the 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) A(ab). Now, given a prime number p p p, how many pairs ( i , j ) (i, j) (i,j) are there such that 1 ≤ i ≤ n , 1 ≤ j ≤ m , A ( i j ) ≡ 0 ( m o d p ) 1≤i≤n, 1≤j≤m, A(ij)≡0(mod p) 1in,1jm,A(ij)0(modp).

输入描述:

The input contains multiple cases. The first line of the input contains a single integer T   ( 1 ≤ T ≤ 100 ) \ (1 \le T \le 100)  (1T100), the number of cases.
For each case, the input consists of a single line, which contains 3 positive integers p , n , m   ( p , n , m ≤ 1 0 9 ) p, n, m \ (p, n, m \leq 10^9) p,n,m (p,n,m109).

输出描述:

Print the answer, a single integer, in one separate line for each case.

示例:

输入:
2
11 8 1
7 6 2

输出:
4
2

解题思路:

在这里插入图片描述
大体思路如图所示,这里再解释一些细节:

  1. 求循环节那里就真的是O(n)的暴力枚举就好了,p是质数,phi(9p) = 6 * (p - 1),枚举phi(9p)的因子f,依次代入验证是否满足 1 0 f ≡ 1 ( m o d 9 p ) 10^f≡1(mod9p) 10f1(mod9p),循环节长度就是最小的满足条件的f。
  2. k i ≤ 30 k_i \leq 30 ki30那里,取极端情况:d的唯一分解只有一个最小的质数2时,因为d <= 1e9,而 2 30 = 1073741824 2^{30} = 1073741824 230=1073741824,比1e9稍微大了一点,所以 k i k_i ki最大取30.

AC代码:

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <string>
#include <set>
#include <vector>
#include <bitset>
using namespace std;
typedef long long ll;
 
const double    PI   = acos(-1.0);
const int       INF  = 0x3f3f3f3f;
const long long LINF = 1e18;
const long long MOD  = 1e9+7;
const int       MAXN = 1e5+10;
 
ll pri[105], fac[105], num = 0;
 
void uniqueDecompose(ll x)//唯一分解,pri为对应质数,fac为对应次数
{
    num = 0;//唯一分解后的质数个数
    for(int j = 2; j*j <= x; j++)
        if(x % j == 0)
        {
            pri[++num] = j, fac[num] = 0;
            while(x % j == 0) fac[num]++, x /= j;
        }
    if(x > 1) pri[++num] = x, fac[num] = 1;
}
 
ll qmul(ll x, ll y, ll m)
{
    ll res = 0;
    while(y)
    {
        if(y & 1) res = (res + x) % m;
        x = (x + x) % m;
        y >>= 1;
    }
    return res;
}
 
ll qpow(ll a, ll n, ll m)
{
    ll res = 1;
    while(n)
    {
        if(n & 1) res = qmul(res, a, m) % m;
        a = qmul(a, a, m) % m, n >>= 1;
    }
    return res;
} 
 
int main()
{
    int t;
    cin >> t;
    while(t--)
    {
        //输入与特判
        ll p, n, m;
        scanf("%lld%lld%lld", &p, &n, &m);
        if(p == 2 || p == 5)
        {
            puts("0");
            continue;
        }
        //求循环节
        ll phi = 6 * (p - 1), d = LINF;//phi(9*p), 循环节
        for(ll i = 1; i*i <= phi; i++)
            if(phi % i == 0)
            {
                ll fac1 = i, fac2 = phi / i;
                if(qpow(10, fac1, 9ll*p) == 1) d = min(d, fac1);
                if(qpow(10, fac2, 9ll*p) == 1) d = min(d, fac2);
            }
        //求有多少对ij使得d|i^j(i的j次方)
        uniqueDecompose(d);
        ll g = 1, ans = 0;
        for(ll i = 1; i <= min(m, 30ll); i++)
        {
            g = 1;
            for(int j = 1; j <= num; j++)
                g *= qpow(pri[j], ceil(1.0*fac[j]/i), 2e9);
            ans += n / g;
        }
        if(m > 30) ans += (m - 30) * (n / g);
        printf("%lld\n", ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值