[2018.10.11 T2] 整除

暫無鏈接

整除

題目描述

整除符號爲|dnd|n 在計算機語言中可被描述爲 n%d==0n\%d == 0
現有一算式nxmxn|x^m − x,給定nmn,m,求[1,n][1, n]以內xx解的個數。
解可能很大,輸出取模998244353998244353

格式
輸入格式

其中nn的給定方式是由cc個不超過tt的質數的乘積給出的,cctt的範圍會在數據範圍中給出。
第一行一個idid表示這個數據點的標號。
多組數據,其中第二行一個整數TT表示數據組數。
對於每一組數據:
第一行兩個整數ccmm
第二行cc個整數,這些整數都是質數,且兩兩不同,他們的乘積即爲nn
由於你可以通過輸入求出tt,輸入不再給出。

輸出格式

對於每組數據輸出一行,表示解的個數。

樣例
樣例輸入

0
1
2 3
2 3

樣例輸出

6
另有兩個樣例,見下發文件。

數據範圍
測試點 cc ≤ tt ≤ mm ≤ TT ≤
11 22 10310^3 22 5050
22 22 10310^3 10910^9 5050
33 22 10210^2 1010 1000010000
44 11 10410^4 22 5050
55 22 10410^4 22 5050
6,7,86,7,8 1010 10410^4 10910^9 5050
9,109,10 5050 10410^4 10910^9 5050

其中所有數據點都滿足1c50,1t104,1m109,1T100001 ≤ c ≤ 50,1 ≤ t ≤ 10^4,1 ≤ m ≤ 10^9,1 ≤ T ≤10000

題解

發現對於nxmx (n=pi)n|x^m-x\ (n=\prod p_i)這個式子的求解,可以化爲對下面這個方程組的求解:
{xmx0mod  p1xmx0mod  p2xmx0mod  pc \left\{ \begin{aligned} &x^m-x\equiv 0\mod p_1\\ &x^m-x\equiv 0\mod p_2\\ &\qquad \vdots \\ &x^m-x\equiv 0\mod p_c\\ \end{aligned} \right.

可以發現,這是一個同餘方程組,那麼根據中國剩餘定理,整個方程組的解的個數便等於方程組中每個方程的解的個數的乘積,我們可以O(p)O(p)的遍歷[1,p][1,p]的所有數來求解每個方程,再將解的個數乘起來得到答案,解決單詞詢問的複雜度爲O((pilogpi))O(\sum (p_i\log p_i))

然而喪心病狂的出題人並不滿足於這樣的複雜度,複雜度瓶頸在於快速冪的logp\log p,考慮我們實際上在處理函數f(x)=xmmod  pf(x)=x^m\mod p[1,p][1,p]內的值,這個函數是積性的,所以f(x)f(x)在合數上的值可以線性篩出來,我們只需要在質數做快速冪,因爲質數的個數約等於pilogpi\frac{p_i}{\log p_i},剛好與快速冪logpi\log p_i抵消,於是最後複雜度降爲O(pi)O(\sum p_i)

代碼
#include<bits/stdc++.h>
using namespace std;
const int M=1e4+5,mod=998244353;
int p[M/3],f[M],sum[M],c,m,T,ans,i,a;
bool vis[M];
int power(int x,int p,int mod){int r=1;for(;p;p>>=1,x=x*x%mod)if(p&1)r=r*x%mod;return r;}
int sie(int n,int m)
{
	int i=2,ans=2,t;
	for(p[0]=0;i<n;++i)
	{
		if(!vis[i])p[++p[0]]=i,f[i]=power(i,m,n);
		for(int j=1;j<=p[0];++j){if((t=i*p[j])>n)break;vis[t]=1;f[t]=f[i]*f[p[j]]%n;if(i%p[j]==0)break;}
		ans+=f[i]==i;
	}
	return ans;
}
void in(){scanf("%d%d",&c,&m);}
void ac(){for(ans=i=1;i<=c;++i)scanf("%d",&a),ans=1ll*ans*sie(a,m)%mod;printf("%d\n",ans);}
int main(){for(scanf("%*d%d",&T);T--;)in(),ac();}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章