dp[i]=sigma(dp[j]*a[i-j])
具有多项式形式可以考虑fft,但是直接会T,考虑cdq分治,每次分治时跑fft即可
#include <cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;
typedef long long LL ;
#define clr( a , x ) memset ( a , x , sizeof a )
const int N = 524300 , P = 313 , M = 1000 ;
int n , pos[N] ;
namespace FFT {
struct comp {
double r , i ;
comp ( double _r = 0 , double _i = 0 ) : r ( _r ) , i ( _i ) {}
comp operator + ( const comp& x ) {
return comp ( r + x.r , i + x.i ) ;
}
comp operator - ( const comp& x ) {
return comp ( r - x.r , i - x.i ) ;
}
comp operator * ( const comp& x ) {
return comp ( r * x.r - i * x.i , i * x.r + r * x.i ) ;
}
comp conj () {
return comp ( r , -i ) ;
}
} A[N] , B[N] ;
const double pi = acos ( -1.0 ) ;
void FFT ( comp a[] , int n , int t ) {
for ( int i = 1 ; i < n ; ++ i ) if ( pos[i] > i ) swap ( a[i] , a[pos[i]] ) ;
for ( int d = 0 ; ( 1 << d ) < n ; ++ d ) {
int m = 1 << d , m2 = m << 1 ;
double o = pi * 2 / m2 * t ;
comp _w ( cos ( o ) , sin ( o ) ) ;
for ( int i = 0 ; i < n ; i += m2 ) {
comp w ( 1 , 0 ) ;
for ( int j = 0 ; j < m ; ++ j ) {
comp& A = a[i + j + m] , &B = a[i + j] , t = w * A ;
A = B - t ;
B = B + t ;
w = w * _w ;
}
}
}
if ( t == -1 ) for ( int i = 0 ; i < n ; ++ i ) a[i].r /= n ;
}
void mul ( int *a , int *b , int *c ,int k) {
int i , j ;
for ( i = 0 ; i < k ; ++ i ) A[i] = comp ( a[i] , b[i] ) ;
j = __builtin_ctz ( k ) - 1 ;
for ( int i = 0 ; i < k ; ++ i ) {
pos[i] = pos[i >> 1] >> 1 | ( ( i & 1 ) << j ) ;
}
FFT ( A , k , 1 ) ;
for ( int i = 0 ; i < k ; ++ i ) {
j = ( k - i ) & ( k - 1 ) ;
B[i] = ( A[i] * A[i] - ( A[j] * A[j] ).conj () ) * comp ( 0 , -0.25 ) ;
}
FFT ( B , k , -1 ) ;
for ( int i = 0 ; i < k ; ++ i ) {
c[i] = ( long long ) ( B[i].r + 0.5 ) % P ;
}
}
}
const int mod=313;
const int maxn=200005;
int dp[maxn];
int a[maxn];
int b[maxn],c[maxn],d[maxn];
void cdq(int l,int r,int n){
if(l==r){
dp[l]+=a[l];
dp[l]%=mod;
return;
}
int mid=(l+r)/2;
cdq(l,mid,n);
int w=1;
while(w<=r-l+1) w=w*2;
for(int i=0;i<w;i++){
if(l+i<=mid) b[i]=dp[i+l];
else b[i]=0;
if((i+1+l)<=r) c[i]=a[i+1]%mod;
else c[i]=0;
}
FFT::mul(b,c,d,w);
for(int i=mid+1;i<=r;i++){
dp[i]+=d[i-l-1];
dp[i]%=mod;
}
cdq(mid+1,r,n);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF){
if(n==0) break;
for(int i=1;i<=n;i++) dp[i]=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
cdq(1,n,n);
printf("%d\n",dp[n]);
}
}