标签:
http://acm.hdu.edu.cn/showproblem.php?pid=5730
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.
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.
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).
3
1 3 7
4
2 2 2 2
0
14
54
题目大概说已知连续i(1<=i<=n)个贝壳组合成一段项链的方案数a[i],求组合成包含n个贝壳的项链的总方案数。
直接枚举转移的话时间复杂度O(n2),是不行的。
其实这个转移方程是个比较特殊的卷积形式,可以用FFT去求,但是从1到n依次求的话时间复杂度是O(n2logn)。
而利用CQD分治,每次治的过程累加左半区间内各个已经求得dp值的状态对右半区间各个状态的贡献,这个贡献就是那个方程用FFT求即可,这样时间复杂度由主定理可知是O(nlog2n)。
这是个很经典的题目吧,虽然现在才做。。
- #include<cstdio>
- #include<cstring>
- #include<cmath>
- #include<algorithm>
- using namespace std;
- #define INF (1<<30)
- #define MAXN 333333
- const double PI=acos(-1.0);
- struct Complex{
- double real,imag;
- Complex(double _real,double _imag):real(_real),imag(_imag){}
- Complex(){}
- Complex operator+(const Complex &cp) const{
- return Complex(real+cp.real,imag+cp.imag);
- }
- Complex operator-(const Complex &cp) const{
- return Complex(real-cp.real,imag-cp.imag);
- }
- Complex operator*(const Complex &cp) const{
- return Complex(real*cp.real-imag*cp.imag,real*cp.imag+cp.real*imag);
- }
- void setValue(double _real=0,double _imag=0){
- real=_real; imag=_imag;
- }
- };
- int len;
- Complex wn[MAXN],wn_anti[MAXN];
- void FFT(Complex y[],int op){
- for(int i=1,j=len>>1,k; i<len-1; ++i){
- if(i<j) swap(y[i],y[j]);
- k=len>>1;
- while(j>=k){
- j-=k;
- k>>=1;
- }
- if(j<k) j+=k;
- }
- for(int h=2; h<=len; h<<=1){
- Complex Wn=(op==1?wn[h]:wn_anti[h]);
- for(int i=0; i<len; i+=h){
- Complex W(1,0);
- for(int j=i; j<i+(h>>1); ++j){
- Complex u=y[j],t=W*y[j+(h>>1)];
- y[j]=u+t;
- y[j+(h>>1)]=u-t;
- W=W*Wn;
- }
- }
- }
- if(op==-1){
- for(int i=0; i<len; ++i) y[i].real/=len;
- }
- }
- void Convolution(Complex A[],Complex B[],int n){
- for(len=1; len<(n<<1); len<<=1);
- for(int i=n; i<len; ++i){
- A[i].setValue();
- B[i].setValue();
- }
- FFT(A,1); FFT(B,1);
- for(int i=0; i<len; ++i){
- A[i]=A[i]*B[i];
- }
- FFT(A,-1);
- }
- int a[111111],d[111111];
- Complex A[MAXN],B[MAXN];
- void cdq(int l,int r){
- if(l==r){
- d[l]+=a[l];
- d[l]%=313;
- return;
- }
- int mid=l+r>>1;
- cdq(l,mid);
- for(int i=l; i<=mid; ++i) A[i-l].setValue(d[i]);
- for(int i=0; i<=r-l; ++i) B[i].setValue(a[i]);
- for(int i=mid-l+1; i<=r-l; ++i) A[i].setValue();
- Convolution(A,B,r-l+1);
- for(int i=mid+1; i<=r; ++i){
- d[i]+=((long long)(A[i-l].real+0.5))%313;
- d[i]%=313;
- }
- cdq(mid+1,r);
- }
- int main(){
- for(int i=0; i<MAXN; ++i){
- wn[i].setValue(cos(2.0*PI/i),sin(2.0*PI/i));
- wn_anti[i].setValue(wn[i].real,-wn[i].imag);
- }
- int n;
- while(~scanf("%d",&n) && n){
- for(int i=1; i<=n; ++i){
- scanf("%d",a+i);
- a[i]%=313;
- }
- memset(d,0,sizeof(d));
- cdq(1,n);
- printf("%d\n",d[n]);
- }
- return 0;
- }
HDU5730 Shell Necklace(DP + CDQ分治 + FFT)
标签:
原文地址:http://www.cnblogs.com/WABoss/p/5886232.html