[题意]
有一串长度为
n
的贝壳项链,装饰连续的
[分析]
设装饰前
i
颗贝壳的方案数为
朴素的计算复杂度为O(n^2),肯定T
观察递推式的形式,考虑用FFT+分治进行优化
计算[L,R]内的
f
时:
先计算[L,M]的
利用已经计算好的[L,M]的
f
值去更新[M+1,R]内的
计算[M+1,R]的
f
值
我们以样例2为例详细说明分治具体过程
a1=a2=a3=a4=2
计算(1,4)
计算(1,2)
计算(1,1)
f1 += a1 => f1=2用FFT计算卷积 {a1}∗{f1}={2}∗{2}={4}
f2 += 4 => f2=4计算(2,2)
f2 += a2 => f2=6用FFT计算卷积 {a1,a2,a3}∗{f1,f2}={2,2,2}∗{2,6}={4,16,16,12}
f3 += 16=>f3=16
f4 += 16=>f4=16计算(3,4)
计算(3,3)
f3 += a3 => f3=18用FFT计算卷积 {a1}∗{f3}={2}∗{18}={36}
f4 += 36 => f4=52计算(4,4)
f4 += a4 => f4=54
[代码]
#include <bits/stdc++.h>
using namespace std ;
const int N = 1e5 + 5 ;
const int mod = 313 ;
const double pi = acos(-1.0) ;
typedef long long LL ;
int n , m ;
int a[N] , f[N] ;
struct Complex
{
double x , y ;
Complex( double x = 0 , double y = 0 ):x(x),y(y) { }
} b[N<<1] , c[N<<1] ;
Complex operator + ( Complex A , Complex B )
{
return Complex(A.x+B.x,A.y+B.y) ;
}
Complex operator - ( Complex A , Complex B )
{
return Complex(A.x-B.x,A.y-B.y) ;
}
Complex operator * ( Complex A , Complex B )
{
return Complex(A.x*B.x-A.y*B.y,A.x*B.y+A.y*B.x) ;
}
Complex operator / ( Complex A , int b )
{
return Complex(A.x/b,A.y/b) ;
}
void change( Complex y[] , int len )
{
for( int i = 1 , j = len>>1 ; i+1 < len ; i++ )
{
if( i < j ) swap(y[i],y[j]) ;
int k = len>>1 ;
while( j >= k )
{
j -= k ;
k >>= 1 ;
}
if( j < k ) j += k ;
}
}
void FFT( Complex y[] , int len , int on )
{
change(y,len) ;
for( int i = 2 ; i <= len ; i <<= 1 )
{
Complex wn(cos(-on*2*pi/i),sin(-on*2*pi/i)) ;
for( int j = 0 ; j < len ; j += i )
{
Complex w(1) ; int o = i>>1 ;
for( int k = j ; k < j+o ; k++ )
{
Complex u = y[k] , t = w * y[k+o] ;
y[k] = u+t ;
y[k+o] = u-t ;
w = w * wn ;
}
}
}
if( on == -1 )
{
for( int i = 0 ; i < len ; i++ )
y[i] = y[i] / len ;
}
}
void cal( int L , int R )
{
if( L == R )
{
f[L] = (f[L]+a[L]) % mod ;
return ;
}
int M = (L+R)>>1 ;
cal(L,M) ;
int len = 1 , m = R-L+1 ;
while( len <= m ) len <<= 1 ;
for( int i = 0 ; i < len ; i++ )
{
if( L+i <= M ) b[i] = Complex(f[L+i]) ;
else b[i] = Complex() ;
if( L+i+1 <= R ) c[i] = Complex(a[i+1]) ;
else c[i] = Complex() ;
}
FFT(b,len,1) ;
FFT(c,len,1) ;
for( int i = 0 ; i < len ; i++ )
b[i] = b[i] * c[i] ;
FFT(b,len,-1) ;
for( int i = M+1 ; i <= R ; i++ )
f[i] = ( f[i] + (int)(b[i-L-1].x+0.5) ) % mod ;
cal(M+1,R) ;
}
int main()
{
while( scanf( "%d" , &n ) , n )
{
for( int i = 1 ; i <= n ; i++ )
{
scanf( "%d" , &a[i] ) ;
a[i] %= mod ;
}
memset(f,0,sizeof(f)) ;
cal(1,n) ;
printf( "%d\n" , f[n] ) ;
}
return 0 ;
}