2019 여름 학교 오프 더 소 세 번째 D 큰 정수

그것은이 문제에서하지 않는 사시간 경주를했다, 경기가 끝나고 결과가 발견 \ (p는 3 \ =) 특별 판사가 잘못했다, 눈물

\ (A (I ^ J) = \ sum_ {K = 0} ^ {I ^ J-1} 10 ^ K = \ FRAC {10 ^ {I ^ J} -1} {9} \ equiv0 (MOD \ 피 ) \)

경우 \ (p \ neq3 \) (지정 키! ①),이 경우 \ (10 ^ {I ^ J } \ equiv1 (MOD \의 P) \)

때 고려 페르마의 소정리 복용 (GCD (10, P) \ = 1 \) , 즉 \ (p의 \의 NEQ 2 \)\ (는 neq5 \는 \ P) (지정 포커스 ②!)가있을 때 \ (10 ^ {I ^ J- (p-1)} \ equiv10 ^ {I ^ JK (p-1)} \의 당량 ... \ equiv10 ^ {I ^ j 개의 \의 % (p-1)} \ equiv1 \ equiv10 ^ 0 (MOD \의 P ) \)

그래서 \ (p 형 1 \ | \ 내가 ^ J \) .

그러나 \ (p-1 \)은 것이 필요는 없다 \ (10 ^ X \ equiv1 ( 개조 \ P가) \) 작은 양의 정수이다 \ (X는 \) , 우리는 설정 \ (Q \)이 가장 작다 (\ X \) 이므로 \ (10 ^ Q의 \의 equiv1 ( 개조 \의 P) \)

분명히 우리가 \ (Q를 \ | \ -THE P-1 \) 그래서 거기에, \ (Q \ | \ 내가 ^ J \) .

\ (Q \)의\ (O (\ SQRT {P } log_2p) \) 시간 복잡도 폭력 얻어진다.

문제는 다음의 숫자로 변환 (1 \ 당량 제가 당량의 \ \ n은 1 \ 당량의 j 개의 \의 당량의 m의 \) 되도록 \ (Q를 \ | \ I ^ J \) .

고려 \ (Q \) 화학식의 소인수 분해 \ (P_1 ^ Q = {P_2 E_1를} ^ {} ... p_x E_2 e_x} ^ {\) , 우리는 한 세트의 설정 \ (P_q = \ {P_1, P_2를. .. p_x \} \)

고려 (I는 \) \ 화학식의 소인수 분해 \을 (^ I = {R_1 R_2 d_1의 파라미터가} ^ {} ... r_y d_2라는 D_y ^ {} \) 설정 \ (P_i = \ {R_1, R_2를 .. ., r_y의 \} \) , 외관상으로 만 때 \는 (P_i \ supset P_q \) 때 것이 가능해야한다 \ (Q를 \ | \ I ^ J \) .

편의를 재기록 \ (나는 \) 화학식 분해 \ (I = P_1 ^ {d_1의 파라미터 } P_2 ^ {d_2라는} ... p_x ^ {d_x} P_ {X + 1} ^ {D_ {X + 1}}. } ^ {D_y \ ..p_y) .

지금이 질문을 고려 : 우리는 고정 된 (내가 \) \를 얼마나 많은, \ (J \) 조건을 만족?

분명히, \ (\ FORALL K \ 당량 X \)\ (jd_k \ GEQ E_k \) 이므로 \ (J \ GEQ \ lceil \ FRAC {E_k} {d_k} \ rceil \)를 따라서, 조건 만족 \을 ( J는 \)\ (최대 M- {} _ { K = 1} ^ X \ lceil \ {FRAC e_k d_k} {} \ rceil + 1 \) 가.

따라서 열거 \ (나는 \) 세는 \ (j의 \) 삭제 최악의 전체 복잡도 \ (O (nlogn) \) (?)

다음으로 우리는 열거 \ (P_1, P_2, ..., p_x \) 지수 \이 (d_1의 파라미터는, d_2라는이, ..., D_X가 \) 의 수를 고려 \을 (1 \ 당량 내가 당량의 \ n 개의 \)를 만든다 화학식 그것 소인수 분해 \ (I = P_1 ^ {F_1 } ^ {P_2 f_2 p_x ...} ^ {F_X} P_ {X + 1} ^ {F_ {X + 1}} ^ {... p_y f_y } \) 에서 \ (= F_1 d_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는 \) 번호는 N {\ (\ lfloor의 \의 FRAC을 {} ^ {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);
    }
}

추천

출처www.cnblogs.com/zhugezy/p/11247545.html