2021hdu多校第二场补题

把求逆序对的操作视为一个长度为p-1的数列进行置换

置换可以抽象为多个环和多个独立点

由线代的一个常识:交换任意两个位置逆序对的奇偶性发生变化,因此只需要讨论置换中交换的次数即点数-圈数即可

p-1 - 圈数

圈可以画成ax -> a^2x ->a^3x -> a^(k-1)x->ax

此时a^k在mod p下同余1

很自然的想到原根 即k=p-1时满足性质  

那么又因为最小的k为置换中圈的长度,所以我们要求出最小的解d满足上述方程来求得圈数为(p-1)/d

直接求d需要枚举p-1的所有因数,在当前数据范围下不可能做到

我们回过头来发现只需要关注p-1 - 圈数的奇偶性即可

再化简到只需要观察(p-1)/d的奇偶性即可

而又表示为p-1 和 d中各自的2的因数个数是否相同即可

能满足a^k在mod p下同余1中的 k 一定能被d整除

假设p-1 = 2^t * q

因此我们考虑枚举 q 2q 4q ....... 2^tq作为d’

此时最小的d'一定有和d一样多的2的因子即可,枚举的次数为logn

而d‘|(p-1)/2的话可知d和p-1二因子个数肯定不同,所以问题又转化为直接检验a^((p-1)/2)是否同余1即可

 

题解做法:

 

相同的结论,只不过更加直观暴力

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define LD long double
#define ull unsigned long long
const LL N=5e5+10;
const LL INF=1e18;
LL a,P,b;
int cnt=0;
void init(){
    return;
}

void add(LL &x,LL y){
    x+=y;if(x>=P)x-=P;
}

LL mul(LL x,LL y){
    LL re=0;
    while(y){
        if(y&1) add(re,x);
        add(x,x);y>>=1;
    } 
    return re;
}

inline long long Mul(long long x,long long y){
    long long tmp=(x*y-(long long)((long double)x/P*y+1.0e-8)*P);
    return (tmp+P)%P;
}

LL qpow(LL x,LL y){
    LL re=1,re2;
    while(y){
        if(y&1) {
            re=Mul(re,x);
        }
        x=Mul(x,x);
        y>>=1;
    }
    return re;
}

void MAIN(){
    scanf("%lld%lld",&a,&P);
    b=qpow(a,(P-1)/2);
    if(b==1) {
        puts("0");
    }
    else{
        puts("1");
    }
    return;
}
int main(){
    init();
    int ttt=1;scanf("%d",&ttt);
    while(ttt--) MAIN();
    return 0;
}

 

posted @ 2021-07-24 01:33  大奕哥&VANE  阅读(179)  评论(0编辑  收藏  举报