• 多项式板子


    持续整理中

    (不会打啊所以就放了)

    这里先放几个散乱的板子,写的非常乱

    合并在一起的板子蜜汁RE了....大力Debug中

    不全,有的没打过

    多项式乘法

    给定两个多项式(A(x)),(B(x)),求(C(x)=A(x)*B(x))。在(mod 998244353)进行。

    FFT模板:

    #include <bits/stdc++.h>
    
    using namespace std;
    
    struct Complex
    {
        double r, v;
        Complex(double rr = 0, double vv = 0) : r(rr), v(vv){}
        Complex &operator=(double x){r = x; v = 0;return *this;}
        friend Complex operator+(const Complex &a, const Complex &b){return Complex(a.r + b.r, a.v + b.v);}
        friend Complex operator-(const Complex &a, const Complex &b){return Complex(a.r - b.r, a.v - b.v);}
        friend Complex operator*(const Complex &a, const Complex &b){return Complex(a.r * b.r - a.v * b.v, a.r * b.v + b.r * a.v);}
    };
    
    int r[4000010];
    Complex a[4000010], b[4000010], ans[4000010];
    int N, M;
    
    void FFT(Complex *A, int n, int flag)
    {
        Complex w, w1, t, *A0, *A1;
        for (int i = 0; i < n; i++)
            if(i < r[i])
                swap(A[i], A[r[i]]);
        for (int i = 1; i < n; i <<= 1)
        {
            w1 = Complex(cos(acos(-1) / i), sin(acos(-1) * flag / i));
            for (int j = 0; j < n; j += i << 1)
            {
                w = 1;
                A0 = A + j;
                A1 = A0 + i;
                for (int k = 0; k < i; k++, A0++, A1++, w = w * w1)
                {
                    t = (*A1) * w;
                    (*A1) = (*A0) - t;
                    (*A0) = (*A0) + t;
                }
            }
        }
    }
    
    int main()
    {
        scanf("%d%d", &N, &M);
        for (int i = 0; i <= N; i++)
            scanf("%lf", &a[i].r);
        for (int i = 0; i <= M; i++)
            scanf("%lf", &b[i].r);
        int tot = 1, len = 0;
        while (tot <= N + M)
            tot <<= 1, len++;
        for (int i = 0; i < tot; i++)
            r[i] = (r[i >> 1] >> 1) | ((i & 1) << (len - 1));
        FFT(a, tot, 1);
        FFT(b, tot, 1);
        for (int i = 0; i < tot; i++)
            ans[i] = a[i] * b[i];
        FFT(ans, tot, -1);
        for (int i = 0; i <= N + M; i++)
            printf("%d%c", (int)(ans[i].r / tot + 0.2) , i == N + M ? '
    ' : ' ');
        return 0;
    }
    

    FNTT模板:

    //rqj 模板 
    #include <bits/stdc++.h>
    using namespace std;
    #define p 998244353
    #define MAXN 4323432
    int n, m;
    int r[MAXN], a[MAXN], b[MAXN], ans[MAXN];
    
    int qpow(int x, int y)
    {
        int ans = 1;
        while (y > 0)
        {
            if (y & 1)
                ans = (1LL * ans * x) % p;
            x = (1LL * x * x) % p;
            y >>= 1;
        }
        return ans;
    }
    
    void FNTT(int *A, int len, int flag)
    {
        int gn, g, t, *A0, *A1;
        for (int i = 0; i < len; i++)
            if (i < r[i])
                swap(A[i], A[r[i]]);
        for (int i = 1; i < len; i <<= 1)
        {
            gn = qpow(3, (p - 1) / (i * 2));
            for (int j = 0; j < len; j += (i << 1))
            {
                g = 1;
                A0 = A + j;
                A1 = A0 + i;
                for (int k = 0; k < i; k++, A0++, A1++, g = (1LL * g * gn) % p)
                {
                    t = (1LL * (*A1) * g) % p;
                    (*A1) = (((*A0) - t) % p + p) % p;
                    (*A0) = ((*A0) + t) % p;
                }
            }
        }
        if (flag == -1)
        {
            reverse(A + 1, A + len);
            int inv = qpow(len, p - 2);
            for (int i = 0; i < len; i++)
                A[i] = (1LL * A[i] * inv) % p;
        }
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
        for (int i = 0; i <= n; i++)
            scanf("%d", &a[i]);
        for (int i = 0; i <= m; i++)
            scanf("%d", &b[i]);
        int len = 1, bin = 0;
        for (; len <= n + m; len <<= 1, bin++);
        for (int i = 0; i < len; i++)
            r[i] = (r[i >> 1] >> 1) | ((i & 1) << (bin - 1));
        FNTT(a, len, 1);
        FNTT(b, len, 1);
        for (int i = 0; i < len; i++)
            ans[i] = (1LL * a[i] * b[i]) % p;
        FNTT(ans, len, -1);
        for (int i = 0; i <= n + m; i++)
            printf("%d%c", ans[i], i == n + m ? '
    ' : ' ');
        return 0;
    }
    

    多项式乘法(任意模数)

    给定两个多项式(A(x)),(B(x)),求(C(x)=A(x)*B(x))。在(mod p)下进行。

    (a_i)拆成(a_{i1}*32768+a_{i2})的形式

    然后都拆开做FFT

    本题精度要求高,omega不能由单位根乘出来,必须要每次使用每次获取。

    #include <bits/stdc++.h>
    using namespace std;
    const double pi = acos(-1);
    struct Complex
    {
        long double r, v;
        Complex(long double rr = 0, long double vv = 0) : r(rr), v(vv){}
        Complex &operator=(long double x){r = x; v = 0;return *this;}
        friend Complex operator+(const Complex &a, const Complex &b){return Complex(a.r + b.r, a.v + b.v);}
        friend Complex operator-(const Complex &a, const Complex &b){return Complex(a.r - b.r, a.v - b.v);}
        friend Complex operator*(const Complex &a, const Complex &b){return Complex(a.r * b.r - a.v * b.v, a.r * b.v + b.r * a.v);}
    };
    
    long long r[543211];
    Complex a1[543211], a2[543211], b1[543211], b2[543211], ans1[543211], ans2[543211], ans3[543211], ans4[543211];long long ans[543211];
    long long a[543211], b[543211];
    long long N, M, p;
    
    long long qpow(long long x, long long y)
    {
        long long ans = 1;
        while (y > 0)
        {
            if (y & 1)
                ans = (1LL * ans * x) % p;
            x = (1LL * x * x) % p;
            y >>= 1;
        }
        return ans;
    }
    
    Complex get_omega(long long x, long long y, long long flag)
    {
        return Complex(std::cos(pi * y / x), std::sin(pi * y / x) * flag);
    }
    
    void FFT(Complex *A, long long n, long long flag)
    {
        Complex w, w1, t, *A0, *A1;
        for (long long i = 0; i < n; i++)
            if(i < r[i])
                swap(A[i], A[r[i]]);
        for (long long i = 1; i < n; i <<= 1)
        {
            for (long long j = 0; j < n; j += i << 1)
            {
                A0 = A + j;
                A1 = A0 + i;
                for (long long k = 0; k < i; k++, A0++, A1++)
                {
                	w = get_omega(i, k, flag);
                    t = (*A1) * w;
                    (*A1) = (*A0) - t;
                    (*A0) = (*A0) + t;
                }
            }
        }
    }
    
    signed main()
    {
        scanf("%lld%lld%lld", &N, &M, &p);
        long long O2 = 32768;
        for (long long i = 0; i <= N; i++)
        {
            scanf("%lld", &a[i]);
            a[i] %= p;
            a1[i].r = a[i] / O2;
            a2[i].r = a[i] % O2;
        }
        for (long long i = 0; i <= M; i++)
        {
            scanf("%lld", &b[i]);
            b[i] %= p;
            b1[i].r = b[i] / O2;
            b2[i].r = b[i] % O2;
        }
        long long tot = 1, len = 0;
        while (tot <= max(N, M) * 2)
            tot <<= 1, len++;
        for (long long i = 0; i < tot; i++)
            r[i] = (r[i >> 1] >> 1) | ((i & 1) << (len - 1));
        FFT(a1, tot, 1);
        FFT(b1, tot, 1);
        FFT(a2, tot, 1);
        FFT(b2, tot, 1);
        for (long long i = 0; i < tot; i++)
        {
        	ans1[i] = a1[i] * b1[i];
        	ans2[i] = a2[i] * b1[i];
        	ans3[i] = a1[i] * b2[i];
        	ans4[i] = a2[i] * b2[i];
        }
        FFT(ans1, tot, -1);
        FFT(ans2, tot, -1);
        FFT(ans3, tot, -1);
        FFT(ans4, tot, -1);
      //  for (long long i = 0; i < tot; i++)
    //    	printf("%Lf %Lf %Lf %Lf
    ", ans1[i].r, ans2[i].r, ans3[i].r, ans4[i].r);
        
        for (long long i = 0; i < tot; i++)
        {
        	ans[i] =				(			(	((((long long)round(ans1[i].r / tot)) % p) + p) % p * O2 %p * O2 % p +
        	           								((((long long)round(ans2[i].r / tot)) % p) + p) % p * O2 % p) % p +
        	          							(	((((long long)round(ans3[i].r / tot)) % p) + p) % p * O2 % p +
        	          								((((long long)round(ans4[i].r / tot)) % p) + p) % p ) % p ) % p;
        }
        for (long long i = 0; i <= N + M; i++)
            printf("%lld%c", ans[i], i == N + M ? '
    ' : ' ');
        return 0;
    }
    

    多项式求逆

    给定一个多项式(F(x)),求出一个多项式(G(x)),满足(F(x)*G(x)equiv1pmod {x^n}),对998244353取模。

    #include <bits/stdc++.h>
    using namespace std;
    #define p 998244353
    #define MAXN 2000010
    
    int n;
    int r[MAXN], A[MAXN], B[MAXN], C[MAXN];
    
    int qpow(int x, int y)
    {
        int ans = 1;
        while (y > 0)
        {
            if (y & 1)
                ans = (1LL * ans * x) % p;
            x = (1LL * x * x) % p;
            y >>= 1;
        }
        return ans;
    }
    
    void FNTT(int *A, int n, int flag)
    {
        int gn, g, t, *A0, *A1;
        for (int i = 0; i < n; i++)
            if (i < r[i])
                swap(A[i], A[r[i]]);
        for (int i = 1; i < n; i <<= 1)
        {
            gn = qpow(3, (p - 1) / (i * 2));
            for (int j = 0; j < n; j += (i << 1))
            {
                g = 1;
                A0 = A + j;
                A1 = A0 + i;
                for (int k = 0; k < i; k++, A0++, A1++, g = (1LL * g * gn) % p)
                {
                    t = (1LL * (*A1) * g) % p;
                    (*A1) = (((*A0) - t) % p + p) % p;
                    (*A0) = ((*A0) + t) % p;
                }
            }
        }
        if (flag == -1)
        {
            reverse(A + 1, A + n);
            int inv = qpow(n, p - 2);
            for (int i = 0; i < n; i++)
                A[i] = (1LL * A[i] * inv) % p;
        }
    }
    
    void poly_inv(int n)
    {
        if (n == 1)
        {
            B[0] = qpow(A[0], p - 2);
            return;
        }
        poly_inv((n + 1) >> 1);
        int len;
        for (len = 1; len <= (n << 1); len <<= 1);
        for (int i = 0; i < len; i++)
            r[i] = (r[i >> 1] >> 1) | ((i & 1) ? (len >> 1) : 0);
        memset(C, 0, sizeof(C));
        for (int i = 0; i < n; i++)
            C[i] = A[i];
        FNTT(C, len, 1);
        FNTT(B, len, 1);
        for (int i = 0; i < len; i++)
            B[i] = 1LL * B[i] * (((2 - 1LL * C[i] * B[i] % p) % p + p) % p) % p;
        FNTT(B, len, -1);
        for (int i = n; i < len; i++)
            B[i] = 0;
    }
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 0; i < n; i++)
        	scanf("%d", &A[i]);
        poly_inv(n);
        for (int i = 0; i < n; i++)
        	printf("%d%c", B[i], i == n - 1 ? '
    ' : ' ');
        return 0;
    }
    

    洛谷分治FFT模板

    #include <bits/stdc++.h>
    using namespace std;
    #define p 998244353
    #define MAXN 2000010
    
    int n;
    int r[MAXN], A[MAXN], B[MAXN], C[MAXN];
    
    int qpow(int x, int y)
    {
        int ans = 1;
        while (y > 0)
        {
            if (y & 1)
                ans = (1LL * ans * x) % p;
            x = (1LL * x * x) % p;
            y >>= 1;
        }
        return ans;
    }
    
    void FNTT(int *A, int n, int flag)
    {
        int gn, g, t, *A0, *A1;
        for (int i = 0; i < n; i++)
            if (i < r[i])
                swap(A[i], A[r[i]]);
        for (int i = 1; i < n; i <<= 1)
        {
            gn = qpow(3, (p - 1) / (i * 2));
            for (int j = 0; j < n; j += (i << 1))
            {
                g = 1;
                A0 = A + j;
                A1 = A0 + i;
                for (int k = 0; k < i; k++, A0++, A1++, g = (1LL * g * gn) % p)
                {
                    t = (1LL * (*A1) * g) % p;
                    (*A1) = (((*A0) - t) % p + p) % p;
                    (*A0) = ((*A0) + t) % p;
                }
            }
        }
        if (flag == -1)
        {
            reverse(A + 1, A + n);
            int inv = qpow(n, p - 2);
            for (int i = 0; i < n; i++)
                A[i] = (1LL * A[i] * inv) % p;
        }
    }
    
    void poly_inv(int n)
    {
        if (n == 1)
        {
            B[0] = qpow(A[0], p - 2);
            return;
        }
        poly_inv((n + 1) >> 1);
        int len;
        for (len = 1; len <= (n << 1); len <<= 1);
        for (int i = 0; i < len; i++)
            r[i] = (r[i >> 1] >> 1) | ((i & 1) ? (len >> 1) : 0);
        memset(C, 0, sizeof(C));
        for (int i = 0; i < n; i++)
            C[i] = A[i];
        FNTT(C, len, 1);
        FNTT(B, len, 1);
        for (int i = 0; i < len; i++)
            B[i] = 1LL * B[i] * (((2 - 1LL * C[i] * B[i] % p) % p + p) % p) % p;
        FNTT(B, len, -1);
        for (int i = n; i < len; i++)
            B[i] = 0;
    }
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i < n; i++)
        {
        	scanf("%d", &A[i]);
        	A[i] = (p - A[i]) % p;
        }
        (A[0] += 1) %= p;
        poly_inv(n);
        for (int i = 0; i < n; i++)
        	printf("%d%c", B[i], i == n - 1 ? '
    ' : ' ');
        return 0;
    }
    

    拉格朗日插值

    给定(n-1)次多项式的(n)个任意(横坐标互不相同)的点的点值式,给定一个x求对应的y。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define p 998244353
    
    struct Vector
    {
        long long x, y;
    }a[2010];
    
    long long N;
    
    long long inv(long long x)
    {
        long long k = p - 2;
        long long ans = 1;
        while (k > 0)
        {
            if (k & 1)
                ans = ans * x % p;
            x = x * x % p;
            k >>= 1;
        }
        return ans;
    }
    
    long long query(long long x)
    {
        long long ans = 0;
        for (int i = 1; i <= N; i++)
        {
            long long tmp = a[i].y;
            for (int j = 1; j <= N; j++)
                if (i != j)
                { 
                    tmp = tmp * (x - a[j].x) % p * inv(a[i].x - a[j].x) % p;
                    tmp = (tmp + p) % p;
                }
            (ans += tmp) %= p;
        }
        return ans;
    } 
    
    int main()
    {
        scanf("%lld", &N);
        long long k;
        scanf("%lld", &k);
        for (int i = 1; i <= N; i++)
            scanf("%lld%lld", &a[i].x, &a[i].y);
        printf("%lld
    ", query(k));
        return 0;
    }
    

    快速沃尔什变换

    给定一个长度为(2^n)的序列A和B

    求序列C满足(displaystyle C_i=sum_{j@k=i}A_j*B_k)当@=or,and,xor时C的值,在(mod998244353)下进行

    #include <bits/stdc++.h>
    #define p 998244353
    using namespace std;
    
    long long a[150000], b[150000], ans[150000];
    int n, len;
    
    void FWT_or(long long *a)
    {
    	for (int i = 1; (i << 1) <= len; i <<= 1)
    		for (int j = 0; j < len; j += i << 1)
    			for (int k = 0; k < i; k++)
    				(a[j + k + i] += a[j + k]) %= p;
    }
    
    void IFWT_or(long long *a)
    {
    	for (int i = 1; (i << 1) <= len; i <<= 1)
    		for (int j = 0; j < len; j += i << 1)
    			for (int k = 0; k < i; k++)
    				(((a[j + k + i] -= a[j + k]) %= p) += p) %= p;
    }
    
    void FWT_and(long long *a)
    {
    	for (int i = 1; (i << 1) <= len; i <<= 1)
    		for (int j = 0; j < len; j += i << 1)
    			for (int k = 0; k < i; k++)
    				(a[j + k] += a[j + k + i]) %= p;
    }
    
    void IFWT_and(long long *a)
    {
    	for (int i = 1; (i << 1) <= len; i <<= 1)
    		for (int j = 0; j < len; j += i << 1)
    			for (int k = 0; k < i; k++)
    				(((a[j + k] -= a[j + k + i]) %= p) += p) %= p;
    }
    
    void FWT_xor(long long *a)
    {
    	for (int i = 1; (i << 1) <= len; i <<= 1)
    		for (int j = 0; j < len; j += i << 1)
    			for (int k = 0; k < i; k++)
    			{
    				long long t = a[j + k];
    				(a[j + k] += a[j + k + i]) %= p;
    				a[j + k + i] = ((t - a[j + k + i]) % p + p) % p;
    			}
    }
    
    long long div2(long long x)
    {
    	return x & 1 ? (x + p) / 2 : x / 2;
    }
    
    void IFWT_xor(long long *a)
    {
    	for (int i = 1; (i << 1) <= len; i <<= 1)
    		for (int j = 0; j < len; j += i << 1)
    			for (int k = 0; k < i; k++)
    			{
    				long long t = a[j + k];
    				a[j + k] = div2(a[j + k] + a[j + k + i]) % p;
    				a[j + k + i] = div2(t - a[j + k + i] + p) % p;
    			}
    }
    
    
    int main()
    {
    	scanf("%d", &n);
    	len = 1 << n;
    	for (int i = 0; i < len; i++)
    		scanf("%lld", &a[i]);
    	for (int i = 0; i < len; i++)
    		scanf("%lld", &b[i]);
    	FWT_or(a);
    	FWT_or(b);
    	for (int i = 0; i < len; i++)
    		ans[i] = a[i] * b[i] % p;
    	IFWT_or(a);
    	IFWT_or(b);
    	IFWT_or(ans);
    	for (int i = 0; i < len; i++)
    		printf("%lld%c", ans[i], i == len - 1 ? '
    ' : ' ');
    	FWT_and(a);
    	FWT_and(b);
    	for (int i = 0; i < len; i++)
    		ans[i] = a[i] * b[i] % p;
    	IFWT_and(a);
    	IFWT_and(b);
    	IFWT_and(ans);
    	for (int i = 0; i < len; i++)
    		printf("%lld%c", ans[i], i == len - 1 ? '
    ' : ' ');
    	FWT_xor(a);
    	FWT_xor(b);
    	for (int i = 0; i < len; i++)
    		ans[i] = a[i] * b[i] % p;
    	IFWT_xor(a);
    	IFWT_xor(b);
    	IFWT_xor(ans);
    	for (int i = 0; i < len; i++)
    		printf("%lld%c", ans[i], i == len - 1 ? '
    ' : ' ');
    	return 0;
    }
    
  • 相关阅读:
    redis你要知道的事
    Nginx七层负载均衡的几种调度算法
    JQuery的父、子、兄弟节点选择器
    laravel通用和万能路由
    jquery竖向企业组织结构图
    phpexcel功能操作
    animatext.js使用介绍
    Centos firewalld开放端口
    获取微信accesstoken并文件缓存方式
    css处理文字不换行、换行截断、溢出省略号
  • 原文地址:https://www.cnblogs.com/oier/p/9716598.html
Copyright © 2020-2023  润新知