多项式板子

持续整理中

(不会打啊所以就放了)

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

合并在一起的板子蜜汁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 ? '\n' : ' ');
    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 ? '\n' : ' ');
    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\n", 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 ? '\n' : ' ');
    return 0;
}

多项式求逆

给定一个多项式\(F(x)\),求出一个多项式\(G(x)\),满足\(F(x)*G(x)\equiv1\pmod {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 ? '\n' : ' ');
    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 ? '\n' : ' ');
    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\n", 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 ? '\n' : ' ');
	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 ? '\n' : ' ');
	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 ? '\n' : ' ');
	return 0;
}
posted @ 2018-09-28 07:08  ghj1222  阅读(157)  评论(0编辑  收藏  举报