ARC166
ARC166
前言
到了 e 难度莫名陡增.......
[ARC166A] Replace C or Swap AB
一个比较简单的贪心
进行交换操作肯定会减少 C 的个数。并且唯一可以变序位置的操作是操作三,所以最后结果一定是 B 尽可能在前。等价于把某个 A 向后移一个位置。贪心地把靠前的 C 都替换成 A。判断当前 X 中是否每个对应的 A 所在位置都不大于它在 Y 中的目标位置即可。
signed main()
{
int T;
cin >> T;
while (T--)
{
int n; string x, y;
cin >> n >> x >> y;
deque<int> q;
bool flag = 0;
for (rint i = 0; i < n; i++)
{
if (y[i] == 'C')
{
if (x[i] != 'C')
{
puts("No");
flag = 1;
break;
}
else q.push_back((int)i);
}
}
if (flag) continue;
int cnt = 0;
q.push_back(n);
while (!q.empty())
{
int a = q.front();
q.pop_front();
int a1 = 0, c1 = 0;
for (rint i = cnt; i < a; i++)
{
if (x[i] == 'A') a1++;
if (x[i] == 'C') c1++;
if (y[i] == 'A')
{
if (!a1 && !c1)
{
puts("No");
flag = 1;
break;
}
if (!a1) c1--;
else a1--;
}
}
if (flag) break;
if (a1 > 0)
{
puts("No");
flag = 1;
break;
}
cnt = a + 1;
}
if (flag) continue;
puts("Yes");
}
return 0;
}
[ARC166B] Make Multiples
传送门link
直接 dp,其实可以不用状态压缩 dp
设 \(f[i][0/1][0/1][0/1]\) 表示前 \(i\) 个数是否有 \(a,b,c\) 的倍数
预处理出来每个数变成某个数的倍数要加上多少然后直接转移
int lcm(int a, int b) {return a * b / __gcd(a, b);}
signed main()
{
cin >> n >> x >> y >> z;
for (rint i = 1; i <= n; i++)
{
int t;
cin >> t;
a[i] = x - (t - 1) % x - 1;
b[i] = y - (t - 1) % y - 1;
c[i] = z - (t - 1) % z - 1;
ab[i] = lcm(x, y) - (t - 1) % lcm(x, y) - 1;
bc[i] = lcm(z, y) - (t - 1) % lcm(z, y) - 1;
ac[i] = lcm(x, z) - (t - 1) % lcm(x, z) - 1;
abc[i] = lcm(lcm(x, y), z) - (t - 1) % lcm(lcm(x, y), z) - 1;
}
memset(f, 0x3f, sizeof f);
f[0][0][0][0] = 0;
for (rint i = 1; i <= n; i++)
{
f[i][0][0][0] = f[i - 1][0][0][0];
f[i][0][0][1] = min(f[i - 1][0][0][1], f[i - 1][0][0][0] + c[i]);
f[i][0][1][0] = min(f[i - 1][0][1][0], f[i - 1][0][0][0] + b[i]);
f[i][1][0][0] = min(f[i - 1][1][0][0], f[i - 1][0][0][0] + a[i]);
f[i][0][1][1] = min({f[i - 1][0][1][1], f[i - 1][0][0][1] + b[i], f[i - 1][0][1][0] + c[i], f[i - 1][0][0][0] + bc[i]});
f[i][1][0][1] = min({f[i - 1][1][0][1], f[i - 1][0][0][1] + a[i], f[i - 1][1][0][0] + c[i], f[i - 1][0][0][0] + ac[i]});
f[i][1][1][0] = min({f[i - 1][1][1][0], f[i - 1][1][0][0] + b[i], f[i - 1][0][1][0] + a[i], f[i - 1][0][0][0] + ab[i]});
f[i][1][1][1] = min({f[i - 1][1][1][1], f[i - 1][1][1][0] + c[i], f[i - 1][1][0][1] + b[i], f[i - 1][0][1][1] + a[i], f[i - 1][0][0][1] + ab[i], f[i - 1][0][1][0] + ac[i], f[i - 1][1][0][0] + bc[i], f[i - 1][0][0][0] + abc[i]});
}
cout << f[n][1][1][1] << endl;
return 0;
}
[ARC166C] LU / RD Marking
传送门link
将边转化成点的问题,染色就是染 \((i,j)\) 和 \((i+1,j-1)\) 位置的点
将点连边。因为染色方式只有一种,所以这个点阵构成了若干条互不相关的斜向的链。
答案是这些链的方案的乘积。
考虑一条边数为 \(n\) 的链。限制为相邻的边不能同时选。
设 \(f_i\) 表示前 \(i\) 条边的方案,因为第 \(i\) 条边若不选,则方案为 \(f_{i-1}\),第 \(i-1\) 条边选不选都无所谓,\(f_i=f_{i-1}+f_{i-2}\)。若第 \(i\) 条边选,则第 \(i-1\) 条边一定不能选,所以从 \(f_{i-2}\) 转移过来。初始态为 \(f_0=1,f_1=2\)(即斐波那契数列)
一个矩形切割出的若干条链的边数是形如 \(1,3,5,7,8,8,8,8,7,5,3,1\) 这样的。对于左右两边可以求一个 \(f\) 序列奇数位的前缀积,中间部分就快速幂。
复杂度 \(O(n+T\log n)\)
signed main()
{
f[0] = 1;
f[1] = s[1] = 2;
for (rint i = 2; i < N; i++) f[i] = (f[i - 1] + f[i - 2]) % mod;
for (rint i = 3; i < N; i++)
{
if (!i % 2) continue;
s[i] = s[i - 2] * f[i] % mod;
}
cin >> T;
while (T--)
{
cin >> n >> m;
if (n > m) swap(n, m);
cout << s[2 * n - 1] * s[2 * n - 1] % mod * qpow(f[2 * n], m - n) % mod << endl;
}
return 0;
}
[ARC166D] Interval Counts
传送门link
假设当前已经满足了 \(1\sim i-1\) 的限制,维护一个队列表示当前还没确定右端点的所有左端点。
如果 \(y_i=y_{i-1}\),让原来右端点接在 \(x_{i-1}\) 的区间接到 \(x_i\)
如果 \(y_i>y_{i-1}\),原来的区间就算全部接到 \(x_i\) 上仍然不够,需要再加 \(y_i-y_{i-1}\) 个左端点为 \(x_{i-1}+1\) 的区间。
如果 \(y_i<y_{i-1}\),说明要删掉 \(y_{i-1}-y_i\) 个区间,由于要让最小值最大,所以需要删掉左端点最小的区间。
于是只维护一个左端点递增的区间,区间数很多,记录这个左端点的个数。
复杂度 \(O(n)\)
int n;
int x[N], y[N];
int ans = inf;
struct node
{
int x, y;
}q[N];
signed main()
{
cin >> n;
for (rint i = 1; i <= n; i++) cin >> x[i];
for (rint i = 1; i <= n; i++) cin >> y[i];
x[0] = -inf;
int head = 1, top = 0;
for (rint i = 1; i <= n; i++)
{
if (y[i] > y[i - 1])
{
q[++top] = {x[i - 1] + 1, y[i] - y[i - 1]};
}
if (y[i] < y[i - 1])
{
int delta = y[i - 1] - y[i];
while(delta && head <= top)
{
int w = min(q[head].y, delta);
delta -= w;
q[head].y -= w;
ans = min(ans, x[i] - 1 - q[head].x);
if (!q[head].y) head++;
else break;
}
}
}
if (ans >= inf) cout << -1 << endl;
else cout << ans << endl;
return 0;
}
[ARC166E] Fizz Buzz Difference
传送门link
在解决这个题目之前,需要学习一个东西。
如何求解线性同余不等式。
给定 \(l,r,a,m(l,r,a\in[0,m),l\le r)\),求最小非负整数 \(x\) 满足:\( l\le ax \bmod m \le r \)
尝试将问题转化为一个更小规模的问题 \(l \le ax-km \le r\)
其中 \(k=\lfloor\frac{ax}{m}\rfloor\)
如果在 \([l,r]\) 之间找到一个 \(a\) 的倍数,即 \(\lfloor\frac{r}{a}\rfloor a\ge l\),这意味着 \(k\) 可以取到最小值 \(0\)。同时,我们直接找到 \(x\) 的一个解:\(\lceil\frac{l}{a}\rceil\)
关于此解的最小性,只看左侧不等式,我们有 \(x\) 是合法解的必要条件 \(ax\ge l+km\),即 \(x\ge\lceil\frac{mk+l}{a}\rceil\),显然此下界关于 \(k\) 是单调递增的,而此解恰好取到了最小下界,故一定是最小的可能合法解,而其合法性显然。
否则,将上式进一步整理为 \(ax-r \le km\le ax-l\)
由于 \([l,r]\) 之间没有 \(a\) 的倍数,设 \(l=pa+u,r=pa+v\),有:\( a(x-p)-v\le km \le a(x-p)-u \)
上式对 \(a\) 取模可得:\(-r \bmod a \le km \bmod a \le -l \bmod a\)
尝试说明当找到该式中 \(k\) 的最小可行解时就能唯一确定 \(x\) 的最小可行解。首先一个原式中可行的 \(x\) 一定对应一个该式中可行的 \(k\),并且对应关系是单调的,即更小的 \(x\) 对应于不会更大的 \(k\),因此我们找到的最小可行 \(k\le\) 最小可行 \(x\) 对应的 \(k\)。同时,对于一个满足上式的 \(k_0\),容易验证一定有 \(x_0=\lfloor\frac{km+r}{a}\rfloor\) 是原式的可行解,且恰好取到下界。
问题转化为求解 \(k\),即 \((-r \bmod a , -l \bmod a,m \bmod a,a)\) 的新问题,问题规模减小,不断递归调用
Code:
int solve(int l, int r, int a, int m)
{
if (l > r || !a) return -1;
if (!l) return 0;
if (r / a * a >= l) return (l - 1) / a + 1;
int k = solve((a - r % a) % a, (a - l % a) % a, m % a, a);
return k == -1 ? -1 : (m * k + l - 1) / a + 1;
}
现在再来处理这道题目。
假设现在这个合法区间是 \([L_0,R_0]\),将 \(R_0\) 不断 \(-1\) 得到一系列区间,它们的 \(n_a-n_b\) 取值一定恰好覆盖 \([1,n]\)。因此 \(n\) 是 \([1,n]\) 中限制最严格的,将题目限制修改为 \(n_a-n_b\le n\)
合法区间一定满足 \(a\mid L-1,a\mid R+1\),否则可以将端点外移让区间长度变长且 \(n_a-n_b\) 不会变大。设 \(L=ak_1+1,R=ak_2-1(k_1<k_2)\),首先来最大化 \(R-L\),即最大化 \(x=k_2-k_1\)
确定 \(x\) 后,\(n_a=x-1\),因此需最大化 \(n_b\)。
一旦确定区间中第一个 \(b\) 的倍数的位置 \(pos\),那么 \(n_b\) 也唯一确定,故只需要最小化 \(pos-L\)。
设 \(g=\gcd(a,b)\),那么 \(pos-L\) 最小能恰好取到 \(g-1\)。因此,确定 \(x\) 后可以直接求得最小可能 \(n_a-n_b\),且此值关于 \(x\) 具有单调性。二分即可。
记求得的最大 \(x\) 为 \(X\),此时区间内至少需要出现 \(c=X-1-n\) 个 \(b\) 的倍数。此限制可以表示为 \(R-L-R\bmod b\ge b(c-1)\),即 \((L+aX-2)\bmod b\in[0, aX-2-b(c-1)]\),如果 \(aX-2-b(c-1)\ge b\),这意味着这条限制不存在,直接令 \(L=1\);否则问题可以转化成 \(ak_1\bmod b\ge (1-aX)\bmod b\),求最小合法 \(k_1\)。刚才上面那个代码就可以快速解决。
复杂度 \(O(T\log V)\)。
int solve(int l, int r, int a, int m)
{
if (l > r || !a) return -1;
if (!l) return 0;
if (r / a * a >= l) return (l - 1) / a + 1;
int k = solve((a - r % a) % a, (a - l % a) % a, m % a, a);
return k == -1 ? -1 : (m * k + l - 1) / a + 1;
}
signed main()
{
int T;
cin >> T;
while (T--)
{
cin >> n >> a >> b;
int g = __gcd(a, b);
int l = 1, r = inf, res;
while (l < r)
{
int mid = (l + r) >> 1;
if (mid - 2 - (a * mid - 1 - g) / b > n) r = mid;
else l = mid + 1, res = mid;
}
int tmp = solve(((1 - a * res) % b + b) % b, b - 1, a, b);
cout << tmp * a + 1 << " " << (tmp + res) * a - 1 << endl;
}
return 0;
}
[ARC166F] Tangent Addition Formula
传送门link
一道不可做的题,看的第一篇题解。懂了但没有完全懂。。。。
\(t\) 的性质二 \(\forall x,y\in \mathbb{N},t(x+y)(1-t(x)t(y))\equiv t(x)+t(y)\pmod p\) 目前没法入手解决,记标记为式 \((\star)\)。
带入 \(x=0,y=0\),得到 \(t(0)(1-t(0)^2)\equiv 2t(0)\pmod p\),解得 \(t(0)=0\) 或 \(t(0)^2\equiv -1\pmod p\)。设 \(I^2\equiv-1\pmod p\),即模 \(p\) 意义下虚数单位,则 \(t(0)\in\{I,-I,0\}\)。
\(t=(0,0,0,\cdots)\) 满足 \((\star)\),说明 \(b=0\) 时 \(t\) 存在。
由和角公式 \(\tan(x+y)=\dfrac{\tan(x)+\tan(y)}{1-\tan(x)\tan(y)}\),对比 \((\star)\),对比可得移了项少了取模。\(t(x)\) 就是某种模意义下的正切函数。
首先展开 \(\tan(x)=\dfrac{\sin(x)}{\cos(x)}\)。
根据欧拉公式 \(e^{ix}=\cos(x)+i\sin(x)\),得到 \(\sin(x)=\dfrac{e^{ix}-e^{-ix}}{2i},\cos(x)=\dfrac{e^{ix}+e^{-ix}}{2}\)。
相除得到 \(\tan(x)=\dfrac{1-(e^{2i})^{x}}{1+(e^{2i})^{x}}\times i\)
形式上 \(\tan(x)\) 形如 \(\dfrac{1-r^{x}}{1+r^{x}}\cdot i\)
【结论 1】
\(t(x)\) 形如 \(\dfrac{1-r^{x}}{1+r^{x}}\cdot I\),其中 \(I^2\equiv -1\pmod p\)。
证明:将该式带入 \((\star)\),得到:
\(t(x+y)(1-t(x)t(y)) = \dfrac{1-r^{x+y}}{1+r^{x+y}}\cdot I\cdot(1-\dfrac{1-r^{x}}{1+r^{x}}\cdot I\cdot\dfrac{1-r^{y}}{1+r^{y}}\cdot I)\)
利用 \(I^2\equiv -1\pmod p\),得到 \(\equiv\dfrac{1-r^{x+y}}{1+r^{x+y}}\cdot I\cdot(1+\dfrac{(1-r^x)(1-r^y)}{(1+r^x)(1+r^y)})\pmod p\)
将分子分母去括号并通分,得到 \(\equiv\dfrac{1-r^{x+y}}{1+r^{x+y}}\cdot I\cdot\dfrac{2(1+r^{x+y})}{1+r^x+r^y+r^{x+y}}\pmod p\)
约分,分解因式,得 \(\equiv I\cdot\dfrac{(1+r^x)(1-r^y)+(1-r^x)(1+r^y)}{(1+r^x)(1+r^y)}\pmod p\)
拆开分子,得 \(\equiv \dfrac{1-r^y}{1+r^y}\cdot I+\dfrac{1-r^x}{1+r^x}\cdot I\pmod p\)
再代回去 \(\equiv t(x)+t(y)\pmod p\)
左边同余于右边,\((\star)\) 成立。原命题得证。
上面除了 \(I^2\equiv -1\pmod p\) 都是恒等变换,因此原问题变成了和 \(I\) 相关的问题。而这个式子,就是二次剩余。
暂记模 \(p\) 意义下的整数域为 \(\mathbb{Z}_p\)
讨论 \(p=2\)
若 \(b=0\),则可以有 \(t=(0,0,0,\cdots)\) 满足 \((\star)\)
若 \(b=1\),则可以有 \(t=(1,1,1,\cdots)\) 满足 \((\star)\)
由于这两种数列的取值和项数无关,对于所有 \(a\) 都能这样取
因此,此时 \(t\) 存在。
讨论 \(p\equiv 1\pmod 4\)
【结论 2】
\(p\equiv 1\pmod 4\Leftrightarrow \exists I\in\mathbb{Z}_p,I^2\equiv-1\pmod p\),其中 \(p\) 为奇质数。
证明:
设 \(p\) 的最小正原根为 \(g\)。由原根存在性定理,\(g\) 存在。
由 \(g^{p-1}\equiv 1\pmod p\),\(g\) 可视为 \(\mathbb{Z}_p\) 下 \(p-1\) 次单位根。由 \(I^4\equiv 1\pmod p\),\(I\) 可视为 \(\mathbb{Z}_p\) 下 \(4\) 次单位根。
因此有 \(I=g^{\frac {p-1} 4}\)。若 \(I\) 存在,则 \(\dfrac {p-1} 4\in\mathbb{Z}\),即 \(4|p-1\)
故若 \(I\) 存在,则 \(p\equiv 1\pmod 4\),必要性得证。
对于充分性,取 \(I\equiv g^{\frac {p-1} 4}\pmod p\),满足题意。
原命题得证。
既然如此,再结合上 \(t(0)\in\{I,-I,0\}\),我们继续分类。
接下来。所有结论都有前提条件 \(p\equiv 1\pmod 4\)。
讨论 \(t(1)\in\{I,-I\}\)
【结论 3】
若 \(t(1)\in\{I,-I\}\),则 \(\forall x\in\mathbb{N^+},t(x)=t(1)\)
数学归纳法,当 \(x=1\) 时显然相等。
现在假设当 \(x=n\in\mathbb{N^+}\) 时成立,即 \(t(n)=t(1)\),下证当 \(x=n+1\) 时成立。
\(t(n+1)(1-t(n)t(1))\equiv t(n)+t(1)\pmod p\)
代入 \(t(n)=t(1)\),得 \(t(n+1)(1-t(1)^2)\equiv 2t(1)\pmod p\)
代入 \(t(1)^2\equiv -1\pmod p\),两边同时除以 \(2\),得到 \(t(n+1)=t(1)\)
原命题得证
由此可得,本类的合法 \(t\) 有且仅有六种情况
\(t=(I,I,I,I,\cdots)\)
\(t=(I,-I,-I,-I,\cdots)\)
\(t=(0,I,I,I,\cdots)\)
\(t=(0,-I,-I,-I,\cdots)\)
\(t=(-I,I,I,I,\cdots)\)
\(t=(-I,-I,-I,-I,\cdots)\)
讨论 \(t(1)\notin\{I,-I\}\)
【结论 4】
若 \(t(1)\notin\{I,-I\}\),则 \(t(0)=0\)
证明:考虑证明其逆否命题,即若 \(t(0)\neq 0\),则 \(t(1)\in\{I,-I\}\)
将 \(x=0,y=1\) 代入 \((\star)\),得到 \(t(1)(1-t(1)t(0))\equiv t(1)+t(0)\pmod p\)。
化简得到 \((t(1)^2+1)t(0)\equiv 0\pmod p\)。
因为 \(t(0)\neq 0\),两边同时除以 \(t(0)\),移项得 \(t(1)^2\equiv -1\pmod p\)
解得 \(t(1)\in\{I,-I\}\)
原命题得证
将特值代入 \((\star)\) 也起不了效果了,只能求助结论 1 了
由于分母不能为 \(0\),所以要求 \(\forall x\in\mathbb{N},r^x\not \equiv-1\pmod p\)。如果存在 \(r\in\mathbb{Z}_p\),则 \(t\) 存在,否则 \(t\) 不存在
由性质三:\(t(a)=b\)。列方程 \(b\equiv \dfrac{1-r^a}{1+r^a}\cdot I\pmod p\)
化简得到 \(r^a\equiv \dfrac{I-b}{I+b}\pmod p\),是个模为质数的高次剩余方程,原根加 BSGS 就能解
在本分类下,\(t\) 存在当且仅当存在 \(r\in\{r|r^a\equiv \dfrac{I-b}{I+b}\pmod p\}\) 使得 \(\forall x\in\mathbb{N},r^x\not\equiv -1\pmod p\)。
讨论 \(p\equiv 3\pmod 4\)
在普通的模意义下整数域上没有
但是高斯整环 \(\mathbb{Z}(i)\) ???
不妨记模 \(p\) 意义下高斯整环为 \(\mathbb{Z}(i)_p=\{a+bi|a,b\in\mathbb{Z}_p\}\),不难得出这玩意是个有限域。
在强行添加上虚数单位后,讨论 \(t\) 的存在条件。
由于对于所有 \(x\in\mathbb{Z}_p\) 可以看作 \(x+0\cdot i\in\mathbb{Z}(i)_p\),因此 \(\mathbb{Z}_p\subseteq\mathbb{Z}(i)_p\)
依题有 \(t(x)=\dfrac{1-r^x}{1+r^x}\cdot i\in\mathbb{Z}_p\),因此 \(r\in\mathbb{Z}(i)_p\) 应该满足 \(\forall x\in\mathbb{N},\dfrac{1-r^x}{1+r^x}\cdot i\in\mathbb{Z}_p\) 且 \(r^x\not\equiv -1\pmod p\)。
判断属不属于集合还是太麻烦了。能不能转化一下?当然可以。我们有如下结论:
【结论 5】
\(\forall x\in\mathbb{N},\dfrac{1-r^x}{1+r^x}\cdot i\in\mathbb{Z}_p\Leftrightarrow r^{p+1}\equiv1\pmod p\)
证明:根据二项式定理有 \((x+y)^p\equiv x^p+y^p\pmod p\)。(仅有 \(\dbinom{p}{0}\) 和 \(\dbinom{p}{p}\) 不能被 \(p\) 整除,其余均含因数 \(p\)。)
设 \(z=x+yi\in\mathbb{Z}_p\),则 \(z^p\equiv x^p+(yi)^p\pmod p\)
由于 \(p\equiv 3\pmod 4\),有 \(i^p=-i\),因此 \(z^p\equiv x^p-y^pi\pmod p\)
根据费马小定理,\(x^p\equiv x\pmod p\),所以 \(z^p\equiv x-yi\pmod p\)
当且仅当 \(y=0\),即 \(z\in\mathbb{Z}_p\) 时,\(z=x-yi\)
故 \(z\in\mathbb{Z}_p\Leftrightarrow z^p\equiv z\pmod p\)
代入 \(z=\dfrac{1-r^x}{1+r^x}\cdot i\),原命题可转化为
\((\dfrac{1-r^x}{1+r^x}\cdot i)^p\equiv\dfrac{1-r^x}{1+r^x}\cdot i\pmod p\Leftrightarrow r^{p+1}\equiv1\pmod p\)
移项有 \((\dfrac{1-r^x}{1+r^x}\cdot i)^p-\dfrac{1-r^x}{1+r^x}\cdot i\equiv 0\pmod p\)
拆括号,得到 \(-\dfrac{(1-r^x)^p}{(1+r^x)^p}\cdot i-\dfrac{1-r^x}{1+r^x}\cdot i\equiv 0\pmod p\)
两边同乘 \(-\dfrac 1 i\),得:\(\dfrac{(1-r^x)^p}{(1+r^x)^p}+\dfrac{1-r^x}{1+r^x}\equiv 0\pmod p\)
用上面二项式定理的推论展开幂次,得 \(\dfrac{1-r^{xp}}{1+r^{x^p}}+\dfrac{1-r^x}{1+r^x}\equiv 0\pmod p\)
通分,得 \(\dfrac{1-(r^{p+1})^x}{1+r^x+r^{px}+r^{(p+1)x}}\equiv 0\pmod p\)
去分母,移项,得 \((r^{p+1})^x\equiv 1\pmod p\)
由于该式对于所有 \(x\) 均成立,可以去掉指数,得 \(r^{p+1}\equiv 1\pmod p\)
充分性得证。以上各式均为恒等变换,反过来可证明必要性 原命题得证。
和上面同样解方程 \(b\equiv \dfrac{1-r^a}{1+r^a}\cdot i\pmod p\),解得 \(r^a\equiv \dfrac{i-b}{i+b}\pmod p\)
不知道原根存在性,没办法 BSGS
\(\mathbb{Z}(i)_p\) 是个有限域吗
这个域共有 \(p^2\) 个元素,根据有限域的存在性和唯一性,其为有限域 \(\mathbb{F}_{p^2}\)
【结论 6】
(有限域原根存在性)
有限域 \(\mathbb{F}\) 存在元素 \(g\) 使得 \(g^n=1,\mathbb{F}=\{g^t|0\le t<n\}\)
综合上述讨论,我们最终得到 \(t\) 的存在性判定方式
当 \(p=2\) 或 \(b=0\) 或 \(b^2\equiv -1\pmod p\) 时,\(t\) 存在
否则,若 \(t\) 存在,则存在 \(r\) 满足以下三个条件
\(r^a\equiv u\pmod p\)
\(r^v\equiv 1\pmod p\)
\(\forall x\in\mathbb{N},r^x\not\equiv-1\pmod p\)
其中 \(u=\dfrac{i-b}{i+b},i^2\equiv-1\pmod p,v=\left\{\begin{matrix} 0 & (p\equiv 1\pmod 4)\\ p+1 & (p\equiv 3\pmod 4) \end{matrix}\right.\)。
记循环群大小 \(n=\left\{\begin{matrix} p-1 & (p\equiv 1\pmod 4)\\ p^2-1 & (p\equiv 3\pmod 4) \end{matrix}\right.\)
设 \(r\equiv g^t\pmod p\),则 \(r^v\equiv g^{tv}\equiv 1\pmod p\)。
由 \(g^n\equiv 1\pmod p\),得到 \(n|tv\),因此有 \(\dfrac n {\gcd(n,v)}|t\)
同理,由 \(r^x\not\equiv-1\pmod p\) 得 \(g^{2tx}\not\equiv1\pmod p\)
因此 \(tx\not\equiv\dfrac n 2\pmod n\)。这玩意可以继续除下去直到 \(n\) 中的 \(2\) 因数被除干净
设 \(2^m|n,2^{m+1}\nmid n\),则可以推出 \(2^m|t\)
所以 \(t\) 的一个取值是 \(\operatorname{lcm}(\dfrac n {\gcd(n,v)},2^m)\)
不妨就令 \(t\) 为该值。则再设 \(r\equiv g^{tk}\)
还差条件一,代入 \(r\) 得 \(g^{atk}\equiv u\)
再和上面一样的做法,得出 \(u^{\frac{n}{\operatorname{gcd}(at, n)}}=1\)
复杂度 \(O(T\log p)\)
int qpow(int a, int b)
{
int res = 1;
while (b)
{
if (b & 1) res = res * a % p;
b >>= 1;
a = a * a % p;
}
return res;
}
struct complex
{
int X, Y;
bool operator == (complex x) {return X == x.X && Y == x.Y;}
complex operator * (complex x)
{
complex s;
s = (complex) {X * x.X % p + imod * x.Y % p * Y % p, Y * x.X % p + X * x.Y % p};
if (s.X >= p) s.X -= p;
if (s.Y >= p) s.Y -= p;
return s;
}
complex operator ^ (int b)
{
complex s({1, 0}), a(*this);
while (b) {if(b & 1) s = s * a;a = a * a;b >>= 1;}
return s;
}
};
signed main()
{
cin >> T;
while (T--)
{
cin >> p >> a >> b;
if (p == 2 || b == 0 || b * b % p + 1 == p)
{
puts("Yes");
continue;
}
if ((p & 3) == 1)
{
n = p - 1;
int f, l;
do
{
l = rand() % p;
imod = l * l % p - (p - 1);
imod < 0 && (imod += p);
}
while (!l || qpow(imod, (p - 1) >> 1) == 1);
f = ((complex) {l, 1} ^ ((p + 1) >> 1)).X;
if (p - f < f) f = p - f;
int t = n / (n & (-n));
t /= __gcd(a, t);
int u = (f - b) * qpow(f + b, p - 2) % p;
if (u < 0) u += p;
if (qpow(u, t) == 1) puts("Yes");
else puts("No");
}
else
{
n = p * p - 1;
imod = p - 1;
int t = n / ((n & (-n)) / __gcd((n & (-n)), p - 1) * (p - 1));
t /= __gcd(a, t);
int inv = qpow(b * b % p + 1, p - 2);
complex u = {(1 - b * b % p + p) * inv % p, (b << 1) % p * inv % p};
if ((u ^ t) == (complex){1, 0}) puts("Yes");
else puts("No");
}
}
return 0;
}