그누텔라 (Gnutella) Chessmaster

주제
이것은 무슬림 연습 수식을 밀어 필요가 없습니다 것입니다.
첫째, 우리는 프로그램에 각각 보드 두 번째에 도착 후, 두 개의 새로운 보드를 얻을, 스테인드 흑백 체스 판을 넣어 (R, R \) \ 다음과가 잘 굴렀다.
관측 가능한 바둑판 \ (B_1 = (1,1,3,3- \ cdots) B_2 = (2,2,4,4- \ cdots) \) , 라인의 수는 \ (N, N-1 \ ) .
내용 (B_1 \) \ 응용 골드먼 Joichi 백색 정리 \ (\ 합계 \ limits_는 {내가 = 0} ^ nr_ix ^ {\ 밑줄 {NI}} = X ^ {\ lfloor \ FRAC N2 \ rfloor} (X + . 1) ^ {\ lceil \ FRAC N2 \ rceil를} \) .
내용 (B_2 \) \ 응용 골드먼 Joichi 백색 정리 \ (\ 합계 \ limits_는 {난 ^ {N-1} R_ix ^ {\ 밑줄 {NI}} = (X + 2) ^ {\ lfloor = 0} \ FRAC N2 \ rfloor} (X +. 1) ^ {\ lceil \ FRAC N2 \ -rceil. 1} \) .
우리는 당신이 얻을 수있는 다항식 다항식의 힘에 일반 감소에 직접 설정 한 경우 \ (O (n \ 로그 ^ 2N) \) 매운 닭 연습.
다 지점 평가, IFDT : 우리는 다항식 전송 전력 다항식 일반 쇠퇴의 과정을 관찰한다.
상기 식에서 IFDT는 변형 EGF에 되감기입니다\ (E ^ {-} X \) , 복잡성 (\ O (N- \ \) N- 로그) 상수는 또한 매우 좋다.
그리고 우리는 분명히 다 지점 평가를 필요로하지 않는, 명백한 캔의 권리는 \ (O (n 여기서 n 로그인 \ ) \) 빠른 멀티 포인트의 평가는 상수 IFDT 위보다 더 우수합니다.
그래서 우리는 두 개의 다항식 전력 강하를 얻을 수 있다는 것을, 당신이 얻을 수있는 역 \ (R, R \) 다음과 잘 굴렀다.

#include<cstdio>
#include<cctype>
#include<algorithm>
#include<cstring>
using std::reverse;
using u64=unsigned long long;
const int N=262150,P=998244353;
namespace IO
{
    char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
    void Put(char x){*oS++=x;if(oS==oT)Flush();}
    int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
    void write(int x){int top=0;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put(' ');}
}using namespace IO;
void swap(int&x,int&y){x^=y^=x^=y;}
int mod(int x){return x+(x>>31&P);}
int mul(int a,int b){return (u64)a*b%P;}
int pow(int a,int k){int r=1;for(;k;k>>=1,a=mul(a,a))if(k&1)r=mul(a,r);return r;}
int w[N],ifac[N],r[N],lim;
void init(int n)
{
    int l=33-__builtin_clz(n),g(pow(3,(P-1)>>l));
    lim=1<<l,ifac[0]=w[lim>>1]=1,--l;
    for(int i=1;i<lim;++i) r[i]=(r[i>>1]>>1)|((i&1)<<l);
    for(int i=1;i<=n;++i) ifac[i]=mul(ifac[i-1],pow(i,P-2));
    for(int i=(lim>>1)+1;i<lim;++i) w[i]=mul(w[i-1],g);
    for(int i=(lim>>1)-1;i;--i) w[i]=w[i<<1];
    return ;
}
void NTT(int*a,int f)
{
    if(!~f) reverse(a+1,a+lim);
    static u64 t[N];
    for(int i=0;i<lim;++i) t[r[i]]=a[i];
    for(int i=1;i<lim;i<<=1) for(int j=0,d=i<<1;j<lim;j+=d) for(int k=0,x;k<i;++k) x=t[i|j|k]*w[i|k]%P,t[i|j|k]=t[j|k]+P-x,t[j+k]+=x;
    for(int i=0;i<lim;++i) a[i]=t[i]%P;
    if(!~f) for(int i=0,p=(P-(P-1)/lim);i<lim;++i) a[i]=mul(a[i],p);
}
int e[N],f[N],g[N];
int main()
{
    int n=read();
    if(n==1) return !printf("1");
    init(n);
    for(int i=0;i<=n;++i) e[i]=i&1? P-ifac[i]:ifac[i];
    for(int i=1;i<=n;++i) f[i]=mul(mul(pow(i,n>>1),pow(i+1,(n+1)/2)),ifac[i]);
    for(int i=0;i<n;++i) g[i]=mul(mul(pow(i+2,n>>1),pow(i+1,(n-1)/2)),ifac[i]);
    NTT(e,1),NTT(f,1),NTT(g,1);
    for(int i=0;i<lim;++i) f[i]=mul(f[i],e[i]),g[i]=mul(g[i],e[i]);
    NTT(f,-1),NTT(g,-1),memset(f+n+1,0,(lim-n-1)<<2),memset(g+n,0,(lim-n)<<2),reverse(f,f+n+1),reverse(g,g+n),NTT(f,1),NTT(g,1);
    for(int i=0;i<lim;++i) f[i]=mul(f[i],g[i]);
    NTT(f,-1);
    for(int i=1;i<n*2;++i) printf("%d ",f[i]);
}

블록 인용

추천

출처www.cnblogs.com/cjoierShiina-Mashiro/p/12169039.html