zoukankan      html  css  js  c++  java
  • hdu 5730 Shell Necklace [分治fft | 多项式求逆]

    hdu 5730 Shell Necklace

    题意:求递推式(f_n = sum_{i=1}^n a_i f_{n-i}),模313


    多么优秀的模板题

    可以用分治fft,也可以多项式求逆

    分治fft

    注意过程中把r-l+1当做次数界就可以了,因为其中一个向量是[l,mid],我们只需要[mid+1,r]的结果。

    多项式求逆

    变成了

    [A(x) = frac{f_0}{1-B(x)} ]

    的形式

    要用拆系数fft,直接把之前的代码复制上就可以啦

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N = (1<<18) + 5, mo = 313;
    const double PI = acos(-1.0);
    inline int read() {
        char c=getchar(); int x=0,f=1;
        while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    struct meow{
        double x, y;
        meow(double a=0, double b=0):x(a), y(b){}
    };
    meow operator +(meow a, meow b) {return meow(a.x+b.x, a.y+b.y);}
    meow operator -(meow a, meow b) {return meow(a.x-b.x, a.y-b.y);}
    meow operator *(meow a, meow b) {return meow(a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x);}
    meow conj(meow a) {return meow(a.x, -a.y);}
    typedef meow cd;
    
    namespace fft {
        int maxlen = 1<<17, rev[N];
        cd omega[N], omegaInv[N];
        void init() {
            for(int i=0; i<maxlen; i++) {
                omega[i] = cd(cos(2*PI/maxlen*i), sin(2*PI/maxlen*i));
                omegaInv[i] = conj(omega[i]);
            }
        }
    
        void dft(cd *a, int n, int flag) {
            cd *w = flag == 1 ? omega : omegaInv;
            int k = 0; while((1<<k) < n) k++;
            for(int i=0; i<n; i++) {
                rev[i] = (rev[i>>1]>>1) | ((i&1)<<(k-1));
                if(i < rev[i]) swap(a[i], a[rev[i]]);
            }
            for(int l=2; l<=n; l<<=1) {
                int m = l>>1;
                for(cd *p = a; p != a+n; p += l) 
                    for(int k=0; k<m; k++) {
                        cd t = w[maxlen/l*k] * p[k+m];
                        p[k+m] = p[k] - t;
                        p[k] = p[k] + t;
                    }
            }
            if(flag == -1) for(int i=0; i<n; i++) a[i].x /= n;
        }
    }
    
    int n, q[N], f[N];
    
    cd a[N], b[N];
    void cdq(int l, int r) {
        using fft::dft;
        if(l == r) return;
        int mid = (l+r)>>1;
        cdq(l, mid);
        int n = 1; while(n < r-l+1) n <<= 1;
        for(int i=0; i<n; i++) a[i] = b[i] = cd();
        for(int i=l; i<=mid; i++) a[i-l].x = f[i];
        for(int i=0; i<=r-l; i++) b[i].x = q[i];
        dft(a, n, 1); dft(b, n, 1);
        for(int i=0; i<n; i++) a[i] = a[i] * b[i];
        dft(a, n, -1);
        for(int i=mid+1; i<=r; i++) f[i] = (f[i] + (int) floor(a[i-l].x + 0.5)) %mo;
        cdq(mid+1, r);
    }
    
    int main() {
        freopen("in", "r", stdin);
        fft::init();
        while( (n=read()) ) {
            //f[0] = 1;
            for(int i=1; i<=n; i++) f[i] = q[i] = read() % mo;
            cdq(0, n);
            printf("%d
    ", f[n] %mo);
        }
    }
    
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N = (1<<18) + 5, mo = 313, P = 313;
    const double PI = acos(-1.0);
    inline int read() {
        char c=getchar(); int x=0,f=1;
        while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    inline int Pow(int a, int b) {
    	int ans = 1;
    	for(; b; b>>=1, a=a*a%P)
    		if(b&1) ans=ans*a%P;
    	return ans;
    }
    
    struct meow{
        double x, y;
        meow(double a=0, double b=0):x(a), y(b){}
    };
    meow operator +(meow a, meow b) {return meow(a.x+b.x, a.y+b.y);}
    meow operator -(meow a, meow b) {return meow(a.x-b.x, a.y-b.y);}
    meow operator *(meow a, meow b) {return meow(a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x);}
    meow conj(meow a) {return meow(a.x, -a.y);}
    typedef meow cd;
    
    namespace fft {
        int maxlen = 1<<18, rev[N];
        cd omega[N], omegaInv[N];
        void init() {
            for(int i=0; i<maxlen; i++) {
                omega[i] = cd(cos(2*PI/maxlen*i), sin(2*PI/maxlen*i));
                omegaInv[i] = conj(omega[i]);
            }
        }
    
        void dft(cd *a, int n, int flag) {
            cd *w = flag == 1 ? omega : omegaInv;
            int k = 0; while((1<<k) < n) k++;
            for(int i=0; i<n; i++) {
                rev[i] = (rev[i>>1]>>1) | ((i&1)<<(k-1));
                if(i < rev[i]) swap(a[i], a[rev[i]]);
            }
            for(int l=2; l<=n; l<<=1) {
                int m = l>>1;
                for(cd *p = a; p != a+n; p += l) 
                    for(int k=0; k<m; k++) {
                        cd t = w[maxlen/l*k] * p[k+m];
                        p[k+m] = p[k] - t;
                        p[k] = p[k] + t;
                    }
            }
            if(flag == -1) for(int i=0; i<n; i++) a[i].x /= n;
        }
    
        cd a[N], b[N], c[N], d[N]; int z[N];
        void inverse(int *x, int *y, int l) {
            if(l == 1) {y[0] = 1; return;}
            inverse(x, y, l>>1);
    		int n = l<<1;
            
            for(int i=0; i<l; i++) a[i] = cd(y[i]>>15), b[i] = cd(y[i]&32767);
            for(int i=l; i<n; i++) a[i] = b[i] = cd();
            dft(a, n, 1); dft(b, n, 1);
            for(int i=0; i<n; i++) {
                cd _a = a[i], _b = b[i];
                a[i] = _a * _a;
                b[i] = _a * _b + _a * _b;
                c[i] = _b * _b;
            }
            dft(a, n, -1); dft(b, n, -1); dft(c, n, -1);
            for(int i=0; i<l; i++)
                z[i] = ( (ll(a[i].x + 0.5) %mo << 30) %mo + (ll(b[i].x + 0.5) %mo << 15) %mo + ll(c[i].x + 0.5) %mo) %mo;
    
            for(int i=0; i<l; i++) 
                a[i] = cd(x[i]>>15), b[i] = cd(x[i]&32767), c[i] = cd(z[i]>>15), d[i] = cd(z[i]&32767); 
            for(int i=l; i<n; i++) a[i] = b[i] = c[i] = d[i] = cd();
            dft(a, n, 1); dft(b, n, 1); dft(c, n, 1); dft(d, n, 1);
            for(int i=0; i<n; i++) {
                cd _a = a[i], _b = b[i], _c = c[i], _d = d[i];
                a[i] = _a * _c;
                b[i] = _a * _d + _b * _c;
                c[i] = _b * _d;
            }
            dft(a, n, -1); dft(b, n, -1); dft(c, n, -1);
            for(int i=0; i<l; i++) {
                ll t = ( (ll(a[i].x + 0.5) %mo << 30) %mo + (ll(b[i].x + 0.5) %mo << 15) %mo + ll(c[i].x + 0.5) %mo) %mo;
                y[i] = (y[i] * 2 %mo - t + mo) %mo;
            }
        }
    }
    
    int n, a[N], b[N];
    int main() {
        freopen("in", "r", stdin);
        fft::init();
        while( (n=read()) ) {
    		memset(b, 0, sizeof(b)); memset(a, 0, sizeof(a));
            for(int i=1; i<=n; i++) b[i] = mo - read() % mo;
    		b[0] = (b[0] + 1) %mo;
    		int len = 1; while(len <= n) len <<= 1;
    		fft::inverse(b, a, len);
            printf("%d
    ", a[n] %mo);
        }
    }
    
    
  • 相关阅读:
    密码学复习
    Kafka Stream 高级应用
    Kafka Stream 流和状态
    Kafka Stream 处理器API
    SSM工作流程与原理详解
    Seata AT和XA模式
    分布式锁结合SpringCache
    使用RabbitMQ最终一致性库存解锁
    使用Springboot+SpringCloud+Seata1.3.0+Nacos1.2.1进行全局事务管理
    在微服务环境下,远程调用feign和异步线程存在请求数据丢失问题
  • 原文地址:https://www.cnblogs.com/candy99/p/6750215.html
Copyright © 2011-2022 走看看