Description
Time Limits: 3000 ms Memory Limits: 262144 KB
Input
Output
Sample Input
0
1
2 3
2 3
Sample Output
6
Data Constraint
思路
考虑题目中的给出素数两两互质这一性质,思考假如N是一个素数时(即c等于1时怎么做)。
很明显此时N<=1e4,则可以从1枚举到N逐个判断。
如果
X
M
≡
X
(
m
o
d
N
)
X^M\equiv X \pmod{N}
XM≡X(modN),则Ans++;
考虑c!=1时,假如这里有一个解
X
t
X_t
Xt,使得
X
t
M
≡
X
t
(
m
o
d
N
)
X_t^M\equiv X_t \pmod{N}
XtM≡Xt(modN),
对于每个质数
P
i
P_i
Pi(i=1,2…c),假如有个解
X
i
j
X_{ij}
Xij使得
X
i
j
M
≡
X
i
j
(
m
o
d
P
i
)
X_{ij}^M\equiv X_{ij}\pmod{P_i}
XijM≡Xij(modPi)。
那么对于每个t与每个i,必有一个j使得,
X
t
≡
X
i
j
(
m
o
d
P
i
)
X_t\equiv X_{ij}\pmod{P_i}
Xt≡Xij(modPi)
考虑
P
i
P_i
Pi是互质的,那么对于每一组
X
i
j
X_{ij}
Xij(每个
P
i
P_i
Pi贡献一个
X
i
j
X_{ij}
Xij出来),
都有唯一的一个
X
t
X_t
Xt使得
{
X
t
≡
X
1
j
(
m
o
d
P
1
)
X
t
≡
X
2
j
(
m
o
d
P
2
)
.
.
.
.
.
.
.
.
.
.
.
.
X
t
≡
X
c
j
(
m
o
d
P
c
)
\begin{cases} X_t\equiv X_{1j}\pmod{P_1}\\ X_t\equiv X_{2j}\pmod{P_2}\\ ............\\ X_t\equiv X_{cj}\pmod{P_c} \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧Xt≡X1j(modP1)Xt≡X2j(modP2)............Xt≡Xcj(modPc)
原因如下:
N
=
P
1
∗
P
2....
∗
P
c
N=P1*P2....*Pc
N=P1∗P2....∗Pc,根据中国剩余定理可得,上面的方程组在[1,N]有且只有1个解,
而对于每个个i,
X
t
m
o
d
X
i
j
X_t \bmod Xij
XtmodXij的值都是唯一的,即每个
X
t
X_t
Xt唯一对应一组
X
i
j
X_{ij}
Xij。
故
X
t
X_t
Xt的个数等于
X
i
j
X_{ij}
Xij的组数,即为每个
P
i
P_i
Pi的j值个数相乘。
而对于每个
P
i
P_i
Pi的j值个数就可以用c=1的方法去做了。
不过,这题卡常。
对于每个
P
i
P_i
Pi值,从1~
P
i
P_i
Pi暴枚其合法解数量并判断是一个O(P*log(M))的复杂度。
总计O(TCPlog(M)),最坏情况是2.5e7乘上long long
取模的常数,很容易被卡。
考虑对于每个 P i P_i Pi,枚举x值时有两种情况:
若x为一个质数,那么直接暴力快速幂算。O(log(M))
若x不为质数,那么把x拆成a*b的形式使得
x
=
a
∗
b
x=a*b
x=a∗b(a!=1且b!=1)。
那么
x
m
=
a
m
∗
b
m
x^m=a^m*b^m
xm=am∗bm,直接O(1)出解。
(先用线性筛预处理一波,减小常数。)
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXC=55;
const int MAXP=10005;
const int MOD=998244353;
const long long ONE=1;
long long Ans;int f[MAXP];
int ID,K,M,C,P[MAXC],poit[MAXP];
int pcnt,prime[MAXP],visp[MAXP];
int quick_Pow(int x,int y,int p){
if(y==0)return 1;
if(y==1)return x;
if(y%2)return (x*quick_Pow((x*x)%p,y/2,p))%p;
return quick_Pow((x*x)%p,y/2,p);
}
inline void Init(int L){
visp[0]=visp[1]=1;
for(int i=2;i<=L;i++){
if(!visp[i])prime[++pcnt]=i;
for(int j=1;j<=pcnt&&prime[j]*i<=L;j++){
visp[i*prime[j]]=1;
poit[i*prime[j]]=prime[j];
if(i%prime[j]==0)break;
}
}
}
int main(){
//freopen("read.in","r",stdin);
//freopen("output.out","w",stdout);
freopen("division.in","r",stdin);
freopen("division.out","w",stdout);
Init(10000);
scanf("%d%d",&ID,&K);
while(K--){
scanf("%d%d",&C,&M);Ans=1;
for(int i=1;i<=C;i++)
scanf("%d",&P[i]);
sort(P+1,P+C+1);
for(int i=1;i<=C;i++){
int ret=2;f[1]=1;
for(int j=2;j<P[i];j++){
if(!visp[j])f[j]=quick_Pow(j,M,P[i]);
else f[j]=(f[poit[j]]*f[j/poit[j]])%P[i];
if((f[j]-j+P[i])%P[i]==0)ret++;
}
Ans=(Ans*ret)%MOD;
}
printf("%lld\n",Ans);
}
}
/*
4
1
2 3
3 37
5
1
3 3
7 11 13
*/
后记
网上还有一种更强的思路,能O(TCLog(t))出解,我就不写了。(原因是我菜爆了写不来 )
https://www.cnblogs.com/zjlcnblogs/p/11299900.html