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;
}

posted @ 2021-08-25 14:46  !^^!  阅读(51)  评论(1)    收藏  举报