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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM