2021杭电多校第二场1010(找规律,快速乘)
2021杭电多校第二场1010(找规律,快速乘)
Problem - 6970 (hdu.edu.cn)
思路:
通过打表,可以得出获得的序列一定是一个长度为p-1的排列
令这个排列为\(\pi\),排列的第i个数为\(\pi(i)\),排列的逆序对数为\(n(\pi)\),计\(sgn(\pi)=(-1)^{n(\pi)}\)
很明显\(sgn(\pi)=\frac{\prod_{0<i<j\le p-1}\pi(i)-\pi(j)}{\prod_{0<i<j\le p-1}i-j}=\prod_{0<i<j\le p-1}\frac{\pi(i)-\pi(j)}{i-j}\)
由本题中的定义\(\pi(i)=ia\ (mod\ p)\)
\(\prod_{0<i<j\le p-1}\frac{\pi(i)-\pi(j)}{i-j}=\prod_{0<i<j\le p-1}\frac{ai-aj}{i-j}=a^{\frac{p(p-1)}{2}}\equiv a^{\frac{p}{2}}\ (mod\ p)\)
这里我个人认为按费马小定理化出来的结果是\(a^{\frac{p}{2}}\),但官方题解这里给了\(a^{\frac{p-1}{2}}\)(可能是为了凑二次剩余的形式看起来好看?),但由于题目保证p为一个奇素数,所以\(\frac{p}{2}=\frac{p-1}{2}\),对答案没有影响。
然后我们只需要计算\(a^{\frac{p}{2}}\ (mod\ p)\) 即可判断\(n(\pi)\)的奇偶
注意\(1\le a,p\le 1e18\)中间需要用到快速乘,但朴素的快速乘会T,题解这里貌似用到了什么黑科技
#include<bits/stdc++.h>
using namespace std;
long long mod;
long long mul(long long a,long long b)
{
long long res=0;
while(b)
{
if(b&1)
{
res=(res+a);
if(res>=mod)res-=mod;
}
a=(a<<1);
if(a>=mod)a-=mod;
b>>=1;
}
return res;
}
inline long long Mul(long long x,long long y){
long long tmp=(x*y-(long long)((long double)x/mod*y+1.0e-8)*mod);
return (tmp+mod)%mod;
}
long long ksm(long long a,long long b)
{
long long res=1;
while(b)
{
if(b&1)res=Mul(res,a);
a=Mul(a,a);
b>>=1;
}
return res;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
long long a;
scanf("%lld%lld",&a,&mod);
if(ksm(a,(mod)/2)==1)puts("0");
else puts("1");
}
return 0;
}