CF300D 광장 회화

광장 회화

https://codeforces.com/problemset/problem/300/D

그는 더 복잡하지만 기본적으로 매우 간단한 프랙탈을 이해했다.

문제 해결

물론, 3 이상의 홀수 광장 및 조작 될 수 있고, 각 동작 시간의 측면 길이 만이다 가운데 사각형의 네 똑같이 크고 작은 사각형으로.

우리는 작업의 수가 M 인하자 및 N을 저감 할 수의 분할 수의 제곱의 크기를 나타낸다 (즉, 최소의 존재 각각 제곱 분할) \ (dp_는 {M, K}는 \) 정방형 M의 동작의 수를 나타낸다 프로그램 피연산자 K 시간.

则有:
\ [dp_ {M, K} = \ sum_ {난 + J + K + L = K-1} dp_ {M-1, I} * dp_ {M-1, J} * dp_ {M-1 , K} * {dp_ M-1, L} \]

7,340,033 계수 NTT 원래 루트. 3이며, NTT 컨벌루션이 전송 될 수있다.

O의 시간 복잡도 (Q 로그 N + K 로그 N 로그 K).

CO int N=4096;
int dp[31][N],tmp[N];
int rev[N],omg[N];

void NTT(int a[],int lim){
    for(int i=0;i<lim;++i)
        if(i<rev[i]) swap(a[i],a[rev[i]]);
    for(int i=1;i<lim;i<<=1)
        for(int j=0;j<lim;j+=i<<1)
            for(int k=0;k<i;++k){
                int t=mul(omg[lim/(i<<1)*k],a[j+i+k]);
                a[j+i+k]=add(a[j+k],mod-t),a[j+k]=add(a[j+k],t);
            }
}
int main(){
    int len=log2(N),lim=N;
    for(int i=0;i<lim;++i) rev[i]=rev[i>>1]>>1|(i&1)<<(len-1);
    omg[0]=1,omg[1]=fpow(3,(mod-1)/lim);
    for(int i=2;i<lim;++i) omg[i]=mul(omg[i-1],omg[1]);
    dp[0][0]=1;
    for(int i=1;i<31;++i){
        copy(dp[i-1],dp[i-1]+lim,tmp);
        NTT(tmp,lim);
        for(int j=0;j<lim;++j) tmp[j]=fpow(tmp[j],4);
        omg[0]=1,omg[1]=fpow(omg[1],mod-2);
        for(int i=2;i<lim;++i) omg[i]=mul(omg[i-1],omg[1]);
        NTT(tmp,lim);
        dp[i][0]=1;
        int ilim=fpow(lim,mod-2);
        for(int j=1;j<1005;++j) dp[i][j]=mul(tmp[j-1],ilim); // edit 1
        omg[0]=1,omg[1]=fpow(omg[1],mod-2);
        for(int i=2;i<lim;++i) omg[i]=mul(omg[i-1],omg[1]);
    }
    for(int q=read<int>();q--;){
        int n=read<int>(),k=read<int>();
        int m=0;
        for(;n>1 and n&1;n>>=1) ++m;
        printf("%d\n",dp[m][k]);
    }
    return 0;
}

폭력 차원 컨볼 루션에도 불구하고 두 번째 값은 1000 DP는 중요하지 않습니다보다 더 큰이지만, 전 DP 기록은 1000을 기록 할 때, 잘못된 다시 기록 할 때. 이것은 아마도 때문에 DP의이면의 기록 된 값은 다음 보간 다수의 원형 컨볼 루션 결과 충분하지 않은 경우.

추천

출처www.cnblogs.com/autoint/p/12013923.html