광장 회화
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의이면의 기록 된 값은 다음 보간 다수의 원형 컨볼 루션 결과 충분하지 않은 경우.