您的位置:首页 > 运维架构 > Shell

【HDU5730】Shell Necklace——CDQ+FFT

2016-11-22 11:08 316 查看
Time Limit: 16000/8000 MS (Java/Others)Memory Limit: 65536/65536 K (Java/Others)

Problem Description

Perhaps the sea‘s definition of a shell is the pearl. However, in my view, a shell necklace with n beautiful shells contains the most sincere feeling for my best lover Arrietty, but even that is not enough.

Suppose the shell necklace is a sequence of shells (not a chain end to end). Considering i continuous shells in the shell necklace, I know that there exist different schemes to decorate the i shells together with one declaration of love.

I want to decorate all the shells with some declarations of love and decorate each shell just one time. As a problem, I want to know the total number of schemes.

Input

There are multiple test cases(no more than 20 cases and no more than 1 in extreme case), ended by 0.

For each test cases, the first line contains an integer n, meaning the number of shells in this shell necklace, where 1≤n≤105. Following line is a sequence with n non-negative integer a1,a2,…,an, and ai≤107 meaning the number of schemes to decorate i continuous shells together with a declaration of love.

Output

For each test case, print one line containing the total number of schemes module 313(Three hundred and thirteen implies the march 13th, a special and purposeful day).

Sample Input

3

1 3 7

4

2 2 2 2

0

Sample Output

14

54

Hint

For the first test case in Sample Input, the Figure 1 provides all schemes about it. The total number of schemes is 1 + 3 + 3 + 7 = 14.

Author

HIT

题意:给你长度为i的项链的组合的情况是a[i],求组成长度为n的项链的方案数。

思路:比较容易想到的就是dp[i]=∑j=0idp[j]×a[i−j],但是n=100000,所以n2的时间复杂度肯定是不行的。对于这种dp前面的结果对后面的结果有贡献的我们可以利用CDQ分治进行解决。对于一个区间我们先处理出前一半的区间的结果,然后计算前一半区间结果对后一半区间的贡献。

假设区间[L,R],mid=L+R2,我们现在已经算出[L,mid],s1=(mid−L+1),s2=(R−L+1),我们构造两个多项式 f1=dp[L]x0+dp[L+1]x1+⋯dp[mid]xs1−1f2=a[0]x0+a[1]x1+a[2]x2⋯a[s2]xs2,那么两个多项式相乘的结果为axy表示对长度为y+L的项链的贡献为a,想想为什么???

这样的话,我们就可以通过CDQ分治的方式降低时间复杂度O(n)log(n)log(n)

#include <bits/stdc++.h>
#define CLR(a,b) memset(a,b,sizeof(a))
using namespace std;
const double Pi = acos(-1.0);
const int maxn = 2e5+100;
const int Mod = 313;
struct Complex{
double real, imag;
Complex(){}
Complex(double _r,double _i):real(_r),imag(_i){}
Complex operator + (const Complex &a) const {
return Complex(real+a.real,imag + a.imag);
}
Complex operator - (const Complex &a) const {
return Complex(real-a.real,imag - a.imag);
}
Complex operator * (const Complex &a) const {
return Complex(real*a.real-imag*a.imag,real*a.imag+imag*a.real);
}
void Setvalue(double r,double i) {
real = r; imag = i;
}
void Output() {
printf("%f %f\n",real,imag);
}
}a[maxn*4],b[maxn*4];
int dp[maxn],num[maxn];
int n,len;
void Rader(Complex y[]) {
for(int i = 1,j = len>>1;i<len-1;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 op) {
Rader(y);
for(int h = 2;h<=len;h<<=1) {
Complex wn(cos(2*Pi*op/h),sin(2*Pi*op/h));
for(int i = 0;i<len;i+=h) {
Complex w(1,0);
for(int j = i;j<i+h/2;j++) {
Complex u = y[j];
Complex v = w*y[j+h/2];
y[j] = u+v;
y[j+h/2] = u-v;
w =w*wn;
}
}
}
if(op == -1) {
for(int i = 0;i<len;i++) y[i].real /= len;
}
}
void CDQ(int L,int R) {//CDQ分治
if(L == R){
return ;
}
int mid = (L+R)>>1;
CDQ(L,mid);
len = 1;
while(len<=(R-L+1)) len<<=1;
for(int i =0;i<len;i++)  a[i].Setvalue(0,0);
for(int i =0;i<len;i++)  b[i].Setvalue(0,0);
for(int i = L;i <= mid; i++)  a[i-L].real+=dp[i];
for(int i = 0;i <R-L+1; i++)  b[i].real += num[i];
FFT(a,1);FFT(b,1);
for(int i = 0;i<len;i++) a[i] = a[i]*b[i];
FFT(a,-1);
for(int i = mid+1;i<=R;i++) {
dp[i]+=(int)(a[i-L].real+0.5);
dp[i]%=Mod;
}
CDQ(mid+1,R);
}
int main() {
while(~scanf("%d",&n) && n) {
CLR(dp,0);CLR(num,0);
for(int i = 1;i<=n;i++) {
scanf("%d",&num[i]);
num[i]%=Mod;
}
dp[0] = 1;
CDQ(0,n);
printf("%d\n",dp
);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: