• BZOJ 5300: [Cqoi2018]九连环 打表+FFT


    仔细观察样例解释,发现 $F(n)=2F(n-1)+[n \%2]$.       

    然后我们就可以推出来前 10 项左右的 $F(n)$ 的值,然后打表找规律发现 $F(n)=frac{2^{n+1}}{3}$ (向下取整) 

    由于没有模数,所以需要手写一个 $FFT$ 维护高精度乘法的板子. 

    code: 

    #include <cstdio> 
    #include <cmath> 
    #include <cstring> 
    #include <algorithm> 
    #define setIO(s) freopen(s".in","r",stdin)  
    using namespace std;   
    const int N=4000006;   
    const double pi=acos(-1);     
    char S[N];  
    struct cp
    {   
        double x,y;   
        cp(double a=0,double b=0) { x=a,y=b; }    
        cp operator+(const cp b) { return cp(x+b.x,y+b.y); }  
        cp operator-(const cp b) { return cp(x-b.x,y-b.y); }  
        cp operator*(const cp b) { return cp(x*b.x-y*b.y,x*b.y+y*b.x); } 
    }A[N],B[N]; 
    int mem[N*10],*ptr=mem;            
    void FFT(cp *a,int len,int flag) 
    {
        int i,j,k,mid;  
        for(i=k=0;i<len;++i) 
        {
            if(i>k) swap(a[i],a[k]);   
            for(j=len>>1;(k^=j)<j;j>>=1);  
        }
        for(mid=1;mid<len;mid<<=1) 
        {
            cp wn(cos(pi/mid), flag*sin(pi/mid)),x,y;
            for(i=0;i<len;i+=mid<<1)
            {
                cp w(1,0);
                for(j=0;j<mid;++j)
                {
                    x=a[i+j],y=w*a[i+j+mid];  
                    a[i+j]=x+y,a[i+j+mid]=x-y; 
                    w=w*wn;        
                }
            }  
        }
        if(flag==-1) 
        {
            for(i=0;i<len;++i) a[i].x/=(double)len;     
        }
    }
    struct num
    {        
        int len; 
        int *a;
        num(){}  
        num(int l) { len=l,a=ptr,ptr+=l; }       
        void fix(int l) { len=l,a=ptr,ptr+=l; }          
        void get_mod(int l) { len=l; }
        num operator*(const num &b) 
        {       
            num c(len+b.len+1);             
            int lim=1,i,j,l=b.len;   
            while(lim<=c.len) lim<<=1;                        
            for(i=0;i<lim;++i) 
            {
                A[i].x=A[i].y=0; 
                B[i].x=B[i].y=0;   
            } 
            for(i=0;i<len;++i) A[i].x=a[i];    
            for(i=0;i<b.len;++i) B[i].x=b.a[i];          
            FFT(A,lim,1),FFT(B,lim,1);   
            for(i=0;i<lim;++i) A[i]=A[i]*B[i];   
            FFT(A,lim,-1);   
            for(i=0;i<c.len;++i) c.a[i]=(int)(A[i].x+0.5);    
    
            for(i=0;i<c.len-1;++i) 
            {   
                c.a[i+1]+=c.a[i]/10;                 
                c.a[i]%=10;      
            }
            for(i=c.len-1;i>=0;--i)  if(c.a[i]) break;              
            c.get_mod(i+1);     
            return c;   
        }          
        num operator/(const int b)     
        {
            num c(len);       
            int i,j,re=0;     
            for(i=len-1;i>=0;--i) 
            {
                re=re*10+a[i];          
                c.a[i]=re/b;                  
                re%=b;          
            }     
            for(i=c.len-1;i>=0;--i) 
            { 
                if(c.a[i]) break;  
            }
            c.get_mod(i+1);   
            return c;     
        } 
        void print() { for(int i=len-1;i>=0;--i) printf("%d",a[i]); }        
        void input() 
        { 
            scanf("%s",S);     
            int l=strlen(S);    
            fix(l);                      
            for(int i=0;i<l;++i) a[i]=S[l-1-i]-'0';     
        }   
    }t,tmp;         
    void qpow(int y) 
    {
        while(y) 
        { 
            if(y&1) tmp=tmp*t;      
            y>>=1;  
            t=t*t;    
        }   
    }      
    int main() 
    {   
        // setIO("input");    
        int m;   
        scanf("%d",&m);     
        while(m--) 
        {
            int n;   
            scanf("%d",&n);   
            tmp.fix(1),t.fix(1);    
            tmp.a[0]=1,t.a[0]=2;          
            qpow(n+1);         
            tmp=tmp/3;   
            tmp.print();     
            printf("
    ");         
        }
        return 0;      
    } 
    

      

  • 相关阅读:
    ASP.NET常见命名空间及其功能描述
    C#中的里氏替换原则
    Java中的split函数的用法
    shader之旅-7-平面阴影(planar shadow)
    OpenGL三角形的双面不同颜色的绘制
    MATLAB squeeze 函数
    matlab 常用函数汇总
    第一个OpenGL程序
    Github 留言系统
    Paging 简单自由的分页生成器
  • 原文地址:https://www.cnblogs.com/guangheli/p/12252730.html
Copyright © 2020-2023  润新知