2019年 第10届山东ACM省赛 K - Happy Equation(数论)

记不太清楚了 - - 按着当时比赛的思路写吧……
先把 a a a 拆开表示成 a = 2 q ∗ k a=2^q*k a=2qk,然后考虑 a x % 2 p = ( 2 q ∗ k ) x % 2 p = ( 2 q ∗ x ∗ k x ) % 2 p a^x\%2^p=(2^q*k)^x\%2^p=(2^{q*x}*k^x)\%2^p ax%2p=(2qk)x%2p=(2qxkx)%2p,那么我们可以分情况讨论一下。
第一种情况, ( 2 q ∗ x ∗ k x ) % 2 p = 0 (2^{q*x}*k^x)\%2^p=0 (2qxkx)%2p=0 p ≤ q ∗ x p \leq q*x pqx ⌈ p q ⌉ ≤ x \lceil \frac{p}{q} \rceil \leq x qpx,此时 x a % 2 p = 0 x^a\%2^p=0 xa%2p=0 也是成立的,设 x = 2 m ∗ l x=2^m*l x=2ml 那么就是要有 2 p ≤ 2 m ∗ a 2^p \leq 2^{m*a} 2p2ma ⌈ p a ⌉ ≤ m \lceil \frac {p}{a} \rceil\leq m apm,因为要求出所有满足题意的 x x x 的个数,那么 m m m 取最小 ⌈ p a ⌉ \lceil \frac {p}{a} \rceil ap,根据 x x x 的取值范围 [ 1 , 2 p ] [1,2^p] [1,2p] 还有刚才求出来的 ⌈ p q ⌉ ≤ x \lceil \frac{p}{q} \rceil \leq x qpx 可以知道 x x x [ ⌈ p q ⌉ , 2 p ] [\lceil \frac{p}{q} \rceil, 2^p] [qp,2p] 中所有 2 m 2^m 2m 的倍数,这一部分的答案个数就是 2 p 2 m − ⌈ p q ⌉ 2 m + [ ⌈ p q ⌉ % 2 m = = 0 ] \frac {2^p}{2^m}-\frac {\lceil \frac{p}{q} \rceil}{2^m}+[\lceil \frac{p}{q} \rceil\%2^m==0] 2m2p2mqp+[qp%2m==0]
第二部分是 ( 2 q ∗ x ∗ k x ) % 2 p ! = 0 (2^{q*x}*k^x)\%2^p !=0 (2qxkx)%2p!=0 x ∗ q < p x*q < p xq<p,由于 p p p 很小直接 for 循环特判 a x % 2 p a^x\%2^p ax%2p x a % 2 p x^a\%2^p xa%2p 即可。

代码

#include 
#include 
#include 
#include 
#include 
using namespace std;

typedef long long ll;

const int maxn = 31;

ll ar[maxn];

void init ()
{
    ar[0] = 1;
    for (int i = 1; i < maxn; ++i) {
        ar[i] = 2*ar[i-1];
    }
}

ll qm (ll a, ll b, ll mod)
{
    ll res = 1;
    while (b) {
        if (b&1) {
            res = res*a%mod;
        }
        a = a*a%mod;
        b >>= 1;
    }
    return res;
}

int main ()
{
    init();
    int t, a, p;
    scanf("%d", &t);
    while (t--) {
        scanf("%d %d", &a, &p);
        int q = 0, v = a;
        while (v % 2 == 0) {
            v /= 2;
            ++q;
        }
        if (q == 0) {
            cout << 1 << '\n';
            continue;
        }
        int bgn = (p%q)?p/q+1:p/q;
        int tmp = (p%a)?p/a+1:p/a;;
        ll res = ar[p]/ar[tmp]-bgn/ar[tmp]+(bgn%ar[tmp]==0);
        for (int x = 1; x*q < p; ++x) {
            if (qm(a, x, ar[p]) == qm(x, a, ar[p])) {
                ++res;
            }
        }
        cout << res << '\n';
    }
    return 0;
}

你可能感兴趣的:(数论)