I love permutation —— 杭电多校第2场 1010
I love permutation
题目链接
题目描述
给定一个 \(a\)和一个奇质数\(p\),令 \(b_x = ax\ mod\ p\),\(x = 1,2,\cdots,p-1\),则 \(b\)序列会形成一个 \(1\)到 \(p-1\)的排列,求这个排列的逆序对数量 \(mod\ 2\)。
解题思路
判断逆序对的奇偶数量可以用下面式子的正负性来判断:
\[sign = \frac{\prod_{1<=j<i< p} b_i - b_j}{\prod_{1<=j<i<p}i - j}
\]
因为 \(b_i\)本身是 \(1 - n\)的排列,所以分子取到了排列里所有不同数的差值,如果不考虑逆序的情况则分子与分母约分正好得出 \(1\),如果存在奇数个逆序对,那么值就为 \(-1\),偶数个逆序对值就为 \(1\)。
将上式化简得出(\(mod p\)):
\[sign = \frac{\prod_{1<=j<i< p} ai - aj}{\prod_{1<=j<i<p}i - j} \equiv a^{{\frac{(p-1)(p-2)}{2}}} \equiv (a^{\frac{p-1}{2}})^{-1}
\]
此时我们考虑当原式值为 \(-1\)时,最后得出的结果二进制最后一位应该为 \(0\),因为 \(-1\ mod\ p = p - 1\),\(p\)为奇数,所以此时结果 \(x\)与 \(1\)相与应为 \(0\);当原式值为1时,最后结果与 \(1\)应该还是 \(1\)。
故需要使用快速幂和快速乘计算出这个值然后进行判断即可。
上面的说明仅供参考!!
这里对官方题解有一个疑问,有待我下去研究,如果有人了解,希望在评论区告知!官方题解上面的公式是这样的:
\[\frac{\prod_{0<j<i< p-1} ai - aj}{\prod_{0<j<i<=p-1}i - j} \equiv a^{{\frac{(p-1)p}{2}}} \equiv (a^{\frac{p-1}{2}})
\]
这个公式的后部分是用了费马小定理 \(a^p \equiv a\)这个公式,但是前半部分我认为应该是求出的 \(a\)的幂次应该是 \(\frac{(p-1)(p-2)}{2}\),因为这就是相当于从 \(p-1\)个数中随便挑出两个,即:\(C_{p-1}^2 = \frac{(p-1)(p-2)}{2}\),不太清楚题解上怎么求的。
Code
#include <bits/stdc++.h>
#define ll long long
#define qc ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
#define fi first
#define se second
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define pb push_back
using namespace std;
const int N = 2e5 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
ll p,a;
ll mul(ll a,ll b){
return(a*b-(ll)(a/(long double)p*b+1e-3)*p+p)%p;
}
ll ksm(ll x,ll y){
ll res = 1;
while(y){
if(y & 1)res = mul(res , x);
x = mul(x , x);
y >>= 1;
}
return res;
}
void solve(){
cin >> a >> p;
ll k = ksm(a,(p-1)>>1);
if(k & 1)cout << 0 << "\n";
else cout << 1 << "\n";
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
qc;
int T = 1;
cin >> T;
while(T--){
solve();
}
return 0;
}
Code will change the world !