UOJ62 怎样跑的更快

b i = ∑ j = 1 n ( i , j ) c − d ∗ i d j d z j b_i=\sum_{j=1}^n(i,j)^{c-d}*i^dj^dz_j bi=j=1n(i,j)cdidjdzj
b i i d = ∑ j = 1 n z j j d ( i , j ) c − d \frac{b_i}{i^d}=\sum_{j=1}^nz_jj^d(i,j)^{c-d} idbi=j=1nzjjd(i,j)cd ( i , j ) = x , B i = b i i d , Z i = z i i d , f i ( d ) = ∑ ( i , j ) = d Z j , F i ( d ) = ∑ d ∣ ( i , j ) Z j (i,j)=x,B_i=\frac{b_i}{i^d},Z_i=z_ii^d,f_i(d)=\sum_{(i,j)=d}Z_j,F_i(d)=\sum_{d|(i,j)}Z_j (i,j)=x,Bi=idbi,Zi=ziid,fi(d)=(i,j)=dZj,Fi(d)=d(i,j)Zj
b i i d = ∑ x ∣ i n f ( x ) x c − d \frac{b_i}{i^d}=\sum_{x|i}^nf(x)x^{c-d} idbi=xinf(x)xcd b i i d = ∑ x ∣ i n x c − d ∑ k F ( k x ) μ ( k ) \frac{b_i}{i^d}=\sum_{x|i}^nx^{c-d}\sum_{k}F(kx)\mu(k) idbi=xinxcdkF(kx)μ(k) b i i d = ∑ k x ∣ i n x c − d F ( k x ) μ ( k ) \frac{b_i}{i^d}=\sum_{kx|i}^nx^{c-d}F(kx)\mu(k) idbi=kxinxcdF(kx)μ(k) B ( i ) = ∑ T ∣ i n F ( T ) ∑ x ∣ T μ ( T / x ) x c − d B(i)=\sum_{T|i}^nF(T)\sum_{x|T}\mu(T/x)x^{c-d} B(i)=TinF(T)xTμ(T/x)xcd 令 g ( T ) = μ ∗ i d c − d ( T ) 令g(T)=\mu*id^{c-d}(T) g(T)=μidcd(T)得到 B ( i ) = ∑ T ∣ i F ( T ) g ( T ) B(i)=\sum_{T|i}F(T)g(T) B(i)=TiF(T)g(T)那么 F ( T ) g ( T ) = ∑ i j = T μ ( j ) B ( i ) F(T)g(T)=\sum_{ij=T}\mu(j)B(i) F(T)g(T)=ij=Tμ(j)B(i)让后一路反推回去得到 z z z就行了

#include
#include
#include
#define N 100010
#define M 998244353
#define LL long long
using namespace std;
inline LL pow(LL x,LL k,int& s){
	while(k<0) k+=M-1;
	for(s=1;k;x=x*x%M,k>>=1) k&1?s=s*x%M:0;
}
int mu[N],c,d,n,q,inv[N];
int f[N],g[N],b[N],B[N],z[N],Z[N],F[N],xd[N],xcd[N],G[N];
int main(){
	scanf("%d%d%d%d",&n,&c,&d,&q);
	mu[1]=1;
	for(int i=1;i<=n;++i){
		pow(i,d,xd[i]);
		pow(i,c-d,xcd[i]);
		pow(xd[i],M-2,inv[i]);
		for(int j=i+i;j<=n;j+=i) mu[j]-=mu[i];
	}
	for(int i=1;i<=n;++i) if(mu[i])
		for(int j=1,k=i;k<=n;++j,k+=i)
			g[k]=(g[k]+mu[i]*xcd[j])%M;
	while(q--){
		for(int i=1;i<=n;++i){
			scanf("%d",b+i);
			B[i]=(LL)b[i]*inv[i]%M;
		}
		memset(G,0,n+1<<2);
		for(int i=1;i<=n;++i) if(mu[i])
			for(int j=1,k=i;k<=n;++j,k+=i)
				G[k]=(G[k]+mu[i]*B[j])%M;
		for(int i=1;i<=n;++i)
			if(!g[i]&&G[i]){
				puts("-1");
				goto end;
			} else{
				pow(g[i],M-2,F[i]); 
				F[i]=(LL)F[i]*G[i]%M;
			}
		memset(Z,0,n+1<<2);
		for(int i=1;i<=n;++i) if(mu[i])
			for(int j=1,k=i;k<=n;++j,k+=i)
				Z[j]=(Z[j]+mu[i]*F[k]%M)%M;
		for(int i=1;i<=n;++i){
			z[i]=(LL)Z[i]*inv[i]%M;
			printf("%d ",(z[i]+M)%M);
		}
		puts(""); end:;
	}
}
		

你可能感兴趣的:(OI,数学,----数论,--------莫比乌斯反演)