• HDU


    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. 

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

    For each test cases, the first line contains an integer nn, meaning the number of shells in this shell necklace, where 1n1051≤n≤105. Following line is a sequence with nnnon-negative integer a1,a2,,ana1,a2,…,an, and ai107ai≤107 meaning the number of schemes to decorate ii continuous shells together with a declaration of love. 
    OutputFor each test case, print one line containing the total number of schemes module 313313(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.

    见:https://blog.csdn.net/Maxwei_wzj/article/details/79850756

    题意:niiai一串项链是n个珠子组成,如果i个珠子连续,可以被认为是    模式i,贡献是ai 
    思路:子,列出DP方程,dp[i]表示长度为i的项链,所有情况的贡献和 dp[i]=∑ dp[j]*A[i-j],复杂度O(N^2)。
    cdq+FFT观察这个式子很像卷积的形式,于是可以用cdq分治+FFT来优化一波 。

    (正确性不难证明,因为分治到Mid+1之前,dp[1]-dp[Mid]的值都已经求出来了。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=100010;
    const int Mod=313;
    const double pi=acos(-1.0);
    struct cp
    {
        double r,i;
        cp(){}
        cp(double rr,double ii):r(rr),i(ii){}
        cp operator +(const cp&x)const{return cp(r+x.r,i+x.i);}
        cp operator -(const cp&x)const{return cp(r-x.r,i-x.i);}
        cp operator *(const cp&x)const{return cp(r*x.r-i*x.i,i*x.r+r*x.i);}
    };
    ll dp[maxn],A[maxn];
    cp a[maxn<<2],b[maxn<<2],W,w,p; int R[maxn<<2],n;
    inline void fft(cp*c,int t)
    {
        int i,j,k;
        for(i=0;i<n;i++) R[i]<i?swap(c[R[i]],c[i]),0:0;
        for(i=1;i<n;i<<=1)
         for(j=0,W={cos(pi/i),sin(pi/i)*t};j<n;j+=i<<1)
          for(k=0,w={1,0};k<i;k++,w=w*W)
           p=c[j+k+i]*w,c[j+k+i]=c[j+k]-p,c[j+k]=c[j+k]+p;
    }
    void solve(int l,int r)
    {
        if(l==r) return ;
        int mid=(l+r)>>1 ;
        solve(l,mid);
        for(n=1;n<((r-l+1));n<<=1);
        rep(i,1,n-1) R[i]=R[i>>1]>>1|(i&1?n>>1:0);
    
        rep(i,0,mid-l) a[i]=cp(dp[l+i],0.);
        rep(i,mid-l+1,n) a[i]=cp(0,0);
    
        rep(i,0,r-l-1) b[i]=cp(A[i+1],0.);
        rep(i,r-l,n) b[i]=cp(0,0);
    
        fft(a,1); fft(b,1);
        rep(i,0,n-1) a[i]=a[i]*b[i];
    
        fft(a,-1);
        rep(i,mid+1,r) dp[i]+=a[i-l-1].r/n+0.5,dp[i]%=Mod;
    
        solve(mid+1,r);
    }
    int main()
    {
        int N;
        while(~scanf("%d",&N)&&N>0){
            rep(i,1,N) dp[i]=0; dp[0]=1;
            rep(i,1,N) scanf("%d",&A[i]),A[i]%=Mod;
            solve(0,N);
            printf("%d
    ",dp[N]);
        }
        return 0;
    }
  • 相关阅读:
    C++每次读取一行字符串输入(学习笔记) (转)
    Ubuntu使用Windows下的conio.h
    容斥原理、欧拉函数、phi
    UVa1635
    转:用STL中的vector动态开辟二维数组
    [转载]Vector用法(C++ Primer中文版)
    c++中vector的pair与make_pair的使用,双关键字排序
    uva12716 GCD XOR
    在 Ubuntu 14.04 中安装 Pepper Flash Player For Chromium
    Careercup
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9662641.html
Copyright © 2020-2023  润新知