Description
对于一个长度为 n n n的正整数序列 A A A和一个正整数 m m m,定义 f ( A , m ) f(A,m) f(A,m)为满足同余方程 ∑ i = 1 n A i x i ≡ 0 ( m o d m ) \sum\limits_{i=1}^n A_ix_i\equiv 0(mod\ m) i=1∑nAixi≡0(mod m) 的向量 x i ∈ [ 0 , m ] x_i\in [0,m] xi∈[0,m]的个数。现在给出一个长度为 n n n的序列 B B B和一个正整数 M M M,记 B B B的 N = 2 n − 1 N=2^n-1 N=2n−1个非空子序列为 A 1 , . . . , A N A_1,...,A_N A1,...,AN,对于每个 m ∈ [ 1 , M ] m\in [1,M] m∈[1,M],求 ∑ i = 1 N f ( A i , m ) \sum\limits_{i=1}^Nf(A_i,m) i=1∑Nf(Ai,m)
Input
第一行一整数 T T T表示用例组数,每组用例首先输入两个整数 n , M n,M n,M,之后输入 n n n个正整数 B i B_i Bi
( 1 ≤ T ≤ 3 , 1 ≤ n , M ≤ 1 0 5 , 1 ≤ B i ≤ 1 0 5 ) (1\le T\le 3,1\le n,M\le 10^5,1\le B_i\le 10^5) (1≤T≤3,1≤n,M≤105,1≤Bi≤105)
Output
令 w m = ∑ i = 1 N f ( A i , m ) m o d 998244353 w_m=\sum\limits_{i=1}^Nf(A_i,m)\ mod\ 998244353 wm=i=1∑Nf(Ai,m) mod 998244353,输出 ⊕ i = 1 M w i \oplus_{i=1}^Mw_i ⊕i=1Mwi,其中 ⊕ \oplus ⊕为异或操作
Sample Input
2 5 5 1 2 3 4 5 10 10 1 2 3 4 5 6 7 8 9 10
Sample Output
1079 933958261
Solution
首先考虑求 f ( A , m ) f(A,m) f(A,m),任意固定 x 1 , . . . , x n − 1 x_1,...,x_{n-1} x1,...,xn−1,假设 A i x i ≡ y i ( m o d m ) A_ix_i\equiv y_i(mod\ m) Aixi≡yi(mod m),显然存在 k k k使得 y 1 + . . . + y n − 1 = k ⋅ g c d ( A 1 , A 2 , . . . , A n − 1 , m ) y_1+...+y_{n-1}=k\cdot gcd(A_1,A_2,...,A_{n-1},m) y1+...+yn−1=k⋅gcd(A1,A2,...,An−1,m) 原方程成立等价于求满足 k ⋅ g c d ( A 1 , . . . , A n − 1 , m ) + A n ⋅ x n ≡ 0 ( m o d m ) k\cdot gcd(A_1,...,A_{n-1},m)+A_n\cdot x_n\equiv 0(mod\ m) k⋅gcd(A1,...,An−1,m)+An⋅xn≡0(mod m) 的 x n x_n xn个数,显然有 g c d ( g c d ( A 1 , m ) , . . . , g c d ( A n , m ) , m ) gcd(gcd(A_1,m),...,gcd(A_n,m),m) gcd(gcd(A1,m),...,gcd(An,m),m)个解,也即 g c d ( A , m ) gcd(A,m) gcd(A,m)个解,故 f ( A , m ) = m n − 1 ⋅ g c d ( A , m ) f(A,m)=m^{n-1}\cdot gcd(A,m) f(A,m)=mn−1⋅gcd(A,m) 假设 B B B序列中为 d d d倍数的数字有 n d n_d nd个,记 f ( d ) f(d) f(d)为 B B B的子序列中满足 g c d ( A , m ) = d gcd(A,m)=d gcd(A,m)=d的 m ∣ A ∣ − 1 m^{|A|-1} m∣A∣−1求和, F ( d ) F(d) F(d)为 B B B的子序列中满足 d ∣ g c d ( A , m ) d|gcd(A,m) d∣gcd(A,m)的 m ∣ A ∣ − 1 m^{|A|-1} m∣A∣−1求和,则有 F ( d ) = ∑ d ∣ i f ( i ) , F ( d ) = ∑ i = 1 n d C n d i ⋅ m i − 1 = ( m + 1 ) n d − 1 m F(d)=\sum\limits_{d|i}f(i),F(d)=\sum\limits_{i=1}^{n_d}C_{n_d}^i\cdot m^{i-1}=\frac{(m+1)^{n_d}-1}{m} F(d)=d∣i∑f(i),F(d)=i=1∑ndCndi⋅mi−1=m(m+1)nd−1 由莫比乌斯反演 f ( d ) = ∑ d ∣ i μ ( i d ) F ( i ) f(d)=\sum\limits_{d|i}\mu(\frac{i}{d})F(i) f(d)=d∣i∑μ(di)F(i) 故有 w m = ∑ i = 1 N f ( A i , m ) = ∑ d ∣ m f ( d ) ⋅ d = ∑ i ∣ m F ( i ) ∑ d ∣ i d ⋅ μ ( i d ) = ∑ d ∣ m φ ( d ) ⋅ F ( d ) w_m=\sum\limits_{i=1}^Nf(A_i,m)=\sum\limits_{d|m}f(d)\cdot d=\sum\limits_{i|m}F(i)\sum\limits_{d|i}d\cdot \mu(\frac{i}{d})=\sum\limits_{d|m}\varphi(d)\cdot F(d) wm=i=1∑Nf(Ai,m)=d∣m∑f(d)⋅d=i∣m∑F(i)d∣i∑d⋅μ(di)=d∣m∑φ(d)⋅F(d) 预处理 φ , F \varphi,F φ,F即可 O ( m l o g m ) O(mlogm) O(mlogm)得到 w 1 , . . . , w m w_1,...,w_m w1,...,wm
Code
#include<cstdio> #include<cstring> using namespace std; typedef long long ll; #define maxn 100005 int euler[maxn],prime[maxn],res; void get_euler(int n=1e5) { euler[1]=1; res=0; for(int i=2;i<=n;i++) { if(!euler[i])euler[i]=i-1,prime[res++]=i; for(int j=0;j<res&&prime[j]*i<=n;j++) { if(i%prime[j]) euler[prime[j]*i]=euler[i]*(prime[j]-1); else { euler[prime[j]*i]=euler[i]*prime[j]; break; } } } } #define mod 998244353 int mul(int x,int y) { ll z=1ll*x*y; return z-z/mod*mod; } int add(int x,int y) { x+=y; if(x>=mod)x-=mod; return x; } int Pow(int x,ll y) { int ans=1; while(y) { if(y&1)ans=mul(ans,x); x=mul(x,x); y>>=1; } return ans; } int T,n,m,b[maxn],a[maxn]; void deal(int x) { for(int i=1;i*i<=x;i++) if(x%i==0) { a[i]++; if(i*i!=x)a[x/i]++; } } int inv[maxn],fact[maxn],sum[maxn],f[maxn]; void init(int n=1e5) { inv[1]=1; for(int i=2;i<=n;i++)inv[i]=mul(mod-mod/i,inv[mod%i]); sum[0]=1; for(int i=1;i<=n;i++)sum[i]=mul(sum[i-1],inv[i]); fact[0]=1; for(int i=1;i<=n;i++)fact[i]=mul(i,fact[i-1]); } int C(int n,int m) { return mul(fact[n],mul(sum[m],sum[n-m])); } int main() { init(); get_euler(); scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); memset(a,0,sizeof(a)); for(int i=1;i<=n;i++) { scanf("%d",&b[i]); deal(b[i]); } memset(f,0,sizeof(f)); for(int i=1;i<=m;i++) for(int j=i;j<=m;j+=i) f[j]=add(f[j],mul(euler[i],mul(add(Pow(j+1,a[i]),mod-1),inv[j]))); int ans=0; for(int i=1;i<=m;i++)ans^=f[i]; printf("%d\n",ans); } return 0; }