[数学推导]对称轴
- 源自校内模拟赛
Statement
-
求
-
[(sum_{i=0}^{p-1}inom{2i}im^i)mod p ]
-
(1le m<ple 10^{14}) ,(p) 为质数
-
多组数据,数据组数不超过 (10^4)
Solution
-
神仙题
-
一个转化:
-
[inom{2n}n=frac 1{(n!)^2}(prod_{i=1}^n(2i-1))(prod_{i=1}^n2i)=frac{2^n}{n!}prod_{i=1}^n(2i-1) ]
-
这看上去没什么用
-
但我们可 (bu) 以 (neng) 想到把 (prod) 里面的每个数都取反后加上 (p) 再除以 (2)
-
[ans=sum_{i=0}^{p-1}frac{(2m)^i}{i!}prod_{j=1}^i(2j-1)=sum_{i=0}^{p-1}frac{(-4m)^i}{i!}prod_{j=1}^i(frac{p+1}2-j) ]
-
[=sum_{i=0}^{p-1}(-4m)^ifrac{prod_{j=1}^i(lfloorfrac p2 floor-j+1)}{i!}=sum_{i=0}^{lfloorfrac p2 floor}inom{lfloorfrac p2 floor}i(-4m)^i=(1-4m)^{lfloorfrac p2 floor} ]
-
于是快速幂套快 (gui) 速乘即可,每组数据 (O(log^2p))
-
当然如果你有高超的打表和猜想技巧,这题是可以被打表水过去的
Code
#include <bits/stdc++.h>
template <class T>
inline void read(T &res)
{
res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
if (bo) res = ~res + 1;
}
typedef long long ll;
ll rqy, m;
ll prod(ll a, ll b)
{
ll res = 0;
while (b)
{
if (b & 1) res = (res + a) % rqy;
a = (a + a) % rqy;
b >>= 1;
}
return res;
}
ll qpow(ll a, ll b)
{
ll res = 1;
while (b)
{
if (b & 1) res = prod(res, a);
a = prod(a, a);
b >>= 1;
}
return res;
}
void work()
{
read(rqy); read(m);
printf("%lld
", qpow((1ll - (m << 2) + (rqy << 2)) % rqy, rqy - 1 >> 1));
}
int main()
{
int T; read(T);
while (T--) work();
return 0;
}