HeHe

tech2022-08-01  153

一、题目

点此看题

H e [ n ] He[n] He[n]为满足 x 2 = x m o d    n x^2=x\mod n x2=xmodn的个数,求 ∏ i = 1 n H e [ i ] m o d    m \prod_{i=1}^n He[i]\mod m i=1nHe[i]modm

二、解法

真正的神题

先把所求做一个等价变换: x ( x − 1 ) = 0 m o d    n x(x-1)=0\mod n x(x1)=0modn我们把 n = p 1 k 1 . . . p m k m n=p_1^{k_1}...p_m^{k_m} n=p1k1...pmkm的质因数划分成两个数 p , q p,q p,q,有 p q = n pq=n pq=n,我们令 x = k 1 p , x − 1 = k 2 q x=k_1p,x-1=k_2q x=k1p,x1=k2q,这样就可以满足上面的条件,但是我们还要满足 k 1 p − k 2 q = 1 k_1p-k_2q=1 k1pk2q=1

p , q p,q p,q固定的情况下,显然上式是一个二元一次方程,因为 p p p q q q互质,而且 0 ≤ k 1 < q 0\leq k_1<q 0k1<q,运用裴蜀定理可知,一定有解,又因为通解的写法是 k 1 = k 1 ′ + r q k_1=k_1'+rq k1=k1+rq,那么在 [ 0 , q ) [0,q) [0,q)内只有一组解,所以对于任意的 p , q p,q p,q,有且仅有一种情况。

p , q p,q p,q的组数很好算,就是 2 m 2^m 2m(每个质因子划分到哪边)

#include <cstdio> #define ll long long const int M = 1e7+5; int read() { int num=0,flag=1; char c; while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1; while(c>='0'&&c<='9')num=(num<<3)+(num<<1)+(c^48),c=getchar(); return num*flag; } int T,n,m,cnt,p[M];bool vis[M]; ll qkpow(ll a,ll b) { ll r=1; while(b>0) { if(b&1) r=r*a%m; a=a*a%m; b>>=1; } return r; } void init(int n) { for(int i=2;i<=n;i++) { if(!vis[i]) p[++cnt]=i; for(int j=1;j<=cnt && i*p[j]<=n;j++) { vis[i*p[j]]=1; if(i%p[j]==0) break; } } } signed main() { T=read(); init(1e7); while(T--) { n=read();m=read(); ll ans=0; for(int i=1;i<=cnt && p[i]<=n;i++) ans+=(n/p[i]); printf("%lld\n",qkpow(2,ans)); } }
最新回复(0)