P7611 [THUPC2021] 幸运位置

P7611 [THUPC2021] 幸运位置

挺奇怪的一道题,虽然各种乱搞可过但还是很有思考价值的。

首先这道题有一个正经的构造做法,\(\gcd(a,b,c)>1\) 时直接判掉无解,设 \(\gcd(b,c)=x\) ,如果 \(x=1\) ,那么 \(n=0\) 就满足条件。

否则我们可以发现 \(\gcd(a+b,x)=1\) (因为有 \(gcd(a,b,c)=1\)),由于一个数 \(x\) 满足 \(\gcd(x,y)=1,\gcd(x,z)=1\) ,那么 \(\gcd(x,yz)=1\) (可以反证),也就是说如果 \(\gcd(a+b,\frac{c}{x})=1\) 那么 \(n=1\) 就是答案。

考虑给 \(a+b\) 加上若干个 \(ax\) ,这样依然有 \(\gcd(kax+a+b,x)=1\) ,现在是要找出一个 \(k\) 满足 \(\gcd(kax+a+b,\frac{c}{x})=1\) ,发现是一个子问题,递归即可。由于 \(x>1\) ,所以顶多递归 \(\log_2{c}\) 层(实际平均只会递归一道两层)。

有两个小问题,第一个是要保证子问题依然有解(不然一个有解的情况递归到无解的情况构造不出了)。考虑归纳证明只要 \(\gcd(a,b,c)=1\) 即有解,那么反证,假设有素数 \(p|\gcd(ax,a+b,c)\) ,那么一定有 \(p|a\)\(p|x\) ,若 \(p|x\) ,则 \(p|b\) ,又因为 \(p|a+b\) ,所以又归到了 \(p|a\) 的情况,那么如果 \(p|a\) ,因为 \(p|a+b\),所以 \(p|b\) ,因为 \(p|c\) ,所以 \(p|\gcd(a,b,c)\) 与前提矛盾。因此递归的任何一个子问题都是有解的。

第二个是解的大小的问题,注意到递归过程中所有 \(x\) 的乘积不超过 \(c\) ,那么最终结果不会超过 \(c\log_2{c}\) ,看起来会超过 \(10^{2000}\) ,但由于跑不满因此不会。

Code 1

from math import gcd
def solve(a,b,c):
    x=gcd(b,c)
    if x==1:
        return 0
    return solve(a*x,a+b,c//x)*x+1

for i in range(int(input())):
    a,b,c=map(int,input().split())
    if gcd(a,gcd(b,c))>1:
        print(-1)
        continue
    print(solve(a,b,c))

但是这道题直接从小到大枚举 \(n\) 或者随机化就可以过。虽然不会严谨的时间复杂度,但是是可以感性理解一下的。

具体来说,关键在于一个数的不同素因子的个数是在 \(O(\log c)\) 级别的,考虑用 \(c\) 的素因子个数对 \(n\) 的最小解进行感性分析。对于一个最小解 \(n'\),也就是说 \(\forall n<n',\gcd(an+b,c)>1\) ,取一个数 \(s\) 和素数 \(t\) 满足 \(s+t<n'\) ,假设 \(p|\gcd(sa+b,c),q|\gcd((s+t)a+b,c)\) ,如果 \(p=q\) ,那么有 \(p|ta\) ,明显 \(p\not|a\) ,否则 \(\gcd(a,b,c)>1\) ,所以有 \(p|t\) ,限制 \(t\) 为素数,那么就有 \(p=t\) ,也就是说有 \(t|c\)

上述分析感性说明一下,就是对于一个间隔为素数的不满足条件的 \(n\) ,要么 \(p\neq q\) ,这样 \(c\) 就会分析出两个不同的素因子,要么 \(p=q\) ,这样这个间隔就是 \(c\) 的素因子,由于 \(c\) 的素因子本来就不会很多, \(n'\) 足够大时其中每一种素数间隔都会至少贡献一种不同的质因子,大胆猜测 \(n\) 的最小解也会是 \(O(\log c)\) 级别的,基于同样的思想我们也可以猜测随机化也只会期望猜 \(O(\log c)\) 次。

当然,上述只是一个非常不严谨的对最小解大小的猜测式的分析,大家看一看就行了。

Code 2

from math import gcd
for i in range(int(input())):
    a,b,c=map(int,input().split())
    if gcd(a,gcd(b,c))>1:
        print(-1)
        continue
    n=0
    while gcd(a*n+b,c)>1:
        n=n+1
    print(n)
posted @ 2022-03-12 09:58  yyyyxh  阅读(22)  评论(0编辑  收藏  举报