跳转至

K - Happy Equation

基本信息

题目出处2019 山东省大学生程序设计竞赛
队伍通过率21/307 (6.8%)

题解

通过打表可以发现,当 a 为奇数时,答案为 1

证明

a 为奇数时,可以证明 x=amod2p 是一个解。

首先,当 a<2p 时,x=amod2p=a 显然满足 ax=xa(mod2p)

a2p 时,根据模的乘法有 ax=xx(mod2p),根据 欧拉定理

xϕ(2p)=x2p1=1(mod2p)

xa=xk×2p+x=x2k×2p1+x=(x2p1)2k×xx=xx=ax(mod2p)

a 为奇数时,若 x 为偶数,则 ax 是奇数,xa 是偶数,不可能对 2p 取模后相等。因此 x 也是奇数。

首先通过反证法证明以下引理。

引理 1:不存在两个奇数 xy 满足 x,y[1,2p]xa=ya(mod2p)

假设存在两个满足要求的奇数 xy,进行因式分解得

xaya=(xy)×i=0a1xiya1i

里的每一项都是奇数,共有 a 项,奇数个奇数项加起来仍然是奇数,不存在质因子 2。而 xy2p1<2p,因此质因子 2 少于 p 个。即

xaya0(mod2p)

与假设矛盾。

v2(t) 表示 t 的质因数分解中 2 的数量。接下来通过反证法证明以下引理。

引理 2:设 x=y(mod2p)v2(x)<pv2(y)<p,则 v2(x)=v2(y)

不失一般性地,假设 v2(x)<v2(y),由题设有

xkx×2p=yky×2p

等式两边同时除以 2v2(x)

x2v2(x)kx×2pv2(x)=y2v2(y)ky×2pv2(x)

x2v2(x) 是奇数,由于 v2(x)<pkx×2pv2(x) 是偶数,因此等式左边是奇数;由于 v2(x)<v2(y)y2v2(y) 是偶数,由于 v2(x)<pky×2pv2(x) 是偶数,因此等式右边是偶数。产生矛盾。

接下来通过反证法证明:不存在两个奇数 xy 满足 1x<y2pax=xa(mod2p)ay=ya(mod2p)

假设存在两个满足要求的奇数 xy,相减得

ayax=yaxa(mod2p)

v2(t) 表示 t 的质因数分解中 2 的数量。由引理 1 得 v2(yaxa)<p,则 v2(ayax)<p(否则 ayax=0yaxa(mod2p)),由引理 2 得 v2(ayax)=v2(yaxa)

根据 升幂(LTE)定理

v2(ayax)=v2(ax(ayx1))(因式分解)=v2(ax(ayx1yx))=v2(ax)+v2(ayx1yx)(根据 v2 的定义)=v2(ax)+v2(a1)+v2(a+1)+v2(yx)1(升幂定理)
v2(yaxa)=v2(yx)(升幂定理)

v2(ax)+v2(a1)+v2(a+1)1=0

因为 ax 是奇数,所以 v2(ax)=0。因为 a 是奇数,当 a3 时,(a1)(a+1) 均为正偶数,因此 v2(a1)1v2(a+1)1。因此

v2(ax)+v2(a1)+v2(a+1)110

产生矛盾。

a=1 时,满足 1x=x1(mod2p)x[1,2p]x 显然只有 x=1

a 为偶数时,设 a 的质因数分解中有 q2,那么 ax 的质因数分解中就有 qx2。当 qxp 时,axmod2p=0。因为 a 是正偶数,即 q1,所以当 xp 时我们只要考虑满足 xamod2p=0x

同样,设 x 的质因数分解中有 k2,那么 xa 的质因数分解中就有 ka2。为了让 xamod2p=0,必须要有 kap,即 kpa=k[p,2p] 中,2k 的倍数有 (2pkp12k) 个。

由于 p30x<p 的部分枚举即可。复杂度 O(plog(a+p))

参考代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <bits/stdc++.h>
using namespace std;

long long power(long long a, int b, int MOD) {
    long long y = 1;
    for (; b; b >>= 1) {
        if (b & 1) y = y * a % MOD;
        a = a * a % MOD;
    }
    return y;
}

void solve() {
    int a, p; scanf("%d%d", &a, &p);
    if (a & 1) { printf("1\n"); return; }

    int ans = 0;
    for (int x = 1; x < p; x++) ans += (power(a, x, 1 << p) == power(x, a, 1 << p) ? 1 : 0);
    int k = (p + a - 1) / a;
    ans += (1 << (p - k)) - (p - 1) / (1 << k);
    printf("%d\n", ans);
}

int main() {
    int tcase; scanf("%d", &tcase);
    while (tcase--) solve();
    return 0;
}