루오 구 [4238] [템플릿] 역 다항식 곱셈

문제의 표면을 보려면 여기를 클릭하십시오

일반적으로, 질문의 의미 부여 다항식 \ (F. (X) \) 추구 \ (G (X) \) 를 만족 \ (F. (X) * G (X) \ equiv1 (MOD \ X ^ N-) \)\ (998,244,353 \) 모듈.

머리말

보드 문제는 문제에 해결책을 복사합니다 ......

나는이 아이디어를 생각하지만, 문제 나 잘 이해에 대한 해결책을보고 열심히하지만, 말해야한다.

푸시 식

우리는이 문제를 해결하기 위해 재귀 수 있습니다.

경계 명백하게 때 재귀 \ (N = 0 \) 를 얻을 수있다 직접 \ (G (X) \) 에서 \ (0 \) 계수 기간 뷰 (즉, 일정 기간)이다 \ (F (X ) \) 에서 \ (0 \) 역 차항의 계수.

그렇지 않으면, 우리가 현재 알고 있다고 가정합니다 :

\ [F (X) * H (X) \ equiv1 (MOD \ X ^ {\ lfloor \ FRAC N2 \ rfloor}) \]

때문에 \ (F. (X) * G는 (X는 equiv1 (MOD는 \ ^ N-X)는 \ \)) , 이것은 명백한

\ [F (X) * G (X) \ equiv1 (MOD \ X ^ {\ lfloor \ FRAC N2 \ rfloor}) \]

우리는이 방정식을 뺄 경우, 당신은 얻을 수 있습니다 :

\ [F (X) * (G (X) -H (X)) \ equiv0 (MOD \ X ^ {\ lfloor \ FRAC N2 \ rfloor}) \]

\ (F (x)의 \) 제거 얻을 :

\ [G (X) -H (X) \ equiv0 (MOD \ X ^ {\ lfloor \ FRAC N2 \ rfloor}) \]

우리는 지금과 대회 다항식의 요구 사항을 고려 \ (F (x)의 \) 회선 모듈 \ (X ^ n \) I \ (1 \) .

우리가에 의해 계수 여기에하자있는 방법을 찾아 내야 것이 분명하다 \ (X ^ {\ lfloor \ FRAC N2 \ rfloor} \) 가된다 \ (n 개의-X 축 ^ \) .

그것을 어떻게? 동시 방정식의 양쪽 사각 캔. 즉 :

\ [(G (X) -H (X)) ^ \ equiv0 2 (MOD \ X ^ N) \]

완벽한 정사각형 공식 광장의 철거 :

\ [G (X) ^ 2-2G (X) * H (X) + H (X) ^ 2 \ equiv0 (MOD \ X ^ N) \]

그런 때 다음 \ (F (x)의 \) 회선까지, 우리가 얻을 :

\ [F (X) * G (X) ^ 2-2F (X) * G (X) * H (X) + F (X) * H (X) ^ 2 \ equiv0 (MOD \ X ^ N) \ ]

이후 \ (F (X 축) * G (X 축) \ equiv1 (MOD \ 상기 n X 축 ^) \) , 우리는 더 간략화 얻을 수 있도록 :

\ [G (X) -2H- (X) + F (X) * H (X) ^ 2 \ equiv0 (MOD \ X ^ N) \]

이 시점에서 우리는 공식 찾을 수 있습니다 \ (G (X)를 \) Shift 키를 통해 얻을 수있는 너무 오래, 독립되었습니다 :

\ [G (X) \ equiv2H (X) - F (X) * H (X) ^ 2 (MOD \ X ^ N) \]

이 수식에서만큼 \ (NTT \) 그것에 다항식 곱셈을 수행.

참고 특정 구현에있어서, 그 \ (G (X) \)\ (H (X) \) 표시 할 수있는 배열.

코드

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define X 998244353
#define Qinv(x) Qpow(x,X-2)
#define swap(x,y) (x^=y^=x^=y)
using namespace std;
int n,a[N+5],b[4*N+5];
class FastIO
{
    private:
        #define FS 100000
        #define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
        #define pc(c) (C==E&&(clear(),0),*C++=c)
        #define tn (x<<3)+(x<<1)
        #define D isdigit(c=tc())
        int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
    public:
        I FastIO() {A=B=FI,C=FO,E=FO+FS;}
        Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
        Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
        Tp I void write(Con Ty& x,Con char& y) {write(x),pc(y);}
        I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
}F;
I int Qpow(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
template<int SZ,int PR> class Poly
{
    private:
        int IPR,P,L,R[4*N+5],t[4*N+5];
        I void T(int *s,CI op)
        {
            RI i,j,k,U,S,x,y;for(i=0;i^P;++i) i<R[i]&&swap(s[i],s[R[i]]);
            for(i=1;i^P;i<<=1) for(U=Qpow(~op?PR:IPR,(X-1)/(i<<1)),j=0;j^P;j+=i<<1)
                for(S=1,k=0;k^i;++k,S=1LL*S*U%X) s[j+k]=((x=s[j+k])+(y=1LL*S*s[i+j+k]%X))%X,s[i+j+k]=(x-y+X)%X;
        }
    public:
        I Poly() {IPR=Qinv(PR);}
        I void Inv(CI n,int *a,int *b)
        {
            if(!n) return (void)(b[0]=Qinv(a[0]));Inv(n>>1,a,b);//处理边界,不在边界则继续递归
            RI i;P=1,L=0;W(P<=(n<<1)) P<<=1,++L;for(i=0;i^P;++i) R[i]=(R[i>>1]>>1)|((i&1)<<L-1);//预处理
            for(i=0;i<=n;++i) t[i]=a[i];T(b,1),T(t,1);//NTT
            for(i=0;i^P;++i) b[i]=(2LL*b[i]%X-1LL*t[i]*b[i]%X*b[i]%X+X)%X;T(b,-1);//计算新多项式
            RI t=Qinv(P);for(i=0;i<=n;++i) b[i]=1LL*b[i]*t%X;for(i=n+1;i^P;++i) b[i]=0;//注意将高位清空,否则会影响后续操作
        }
};Poly<N,3> P;
int main()
{
    RI i;for(F.read(n),--n,i=0;i<=n;++i) F.read(a[i]);//读入
    for(P.Inv(n,a,b),i=0;i<=n;++i) F.write(b[i]," \n"[i==n]);return F.clear(),0;//输出
}

추천

출처www.cnblogs.com/chenxiaoran666/p/Luogu4238.html