uoj #34. 多项式乘法 多项式乘法模板

版权声明:本博客内容基本为原创,如有问题欢迎联系,未经允许请勿转载 https://blog.csdn.net/qq_41955236/article/details/82016507

这是一道模板题。

给你两个多项式,请输出乘起来后的多项式。

输入格式

第一行两个整数 nn 和 mm,分别表示两个多项式的次数。

第二行 n+1n+1 个整数,表示第一个多项式的 00 到 nn 次项系数。

第三行 m+1m+1 个整数,表示第二个多项式的 00 到 mm 次项系数。

输出格式

一行 n+m+1n+m+1 个整数,表示乘起来后的多项式的 00 到 n+mn+m 次项系数。

样例一

input

1 2
1 2
1 2 1

output

1 4 5 2

explanation

(1+2x)⋅(1+2x+x2)=1+4x+5x2+2x3(1+2x)⋅(1+2x+x2)=1+4x+5x2+2x3。

限制与约定

0≤n,m≤1050≤n,m≤105,保证输入中的系数大于等于 00 且小于等于 99。

时间限制:1s1s

空间限制:256MB


模板题就不解释了吧,多项式乘法,用了NTT(数论变换)。表示不是很懂但是。。模板留着用用吧。。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1 << 20;
typedef long long ll;
const ll mo = 998244353;
ll fpow(ll a, ll b)
{
    ll ans = 1;
    while (b > 0) { if (b & 1)ans = ans * a%mo; b >>= 1; a = a * a%mo; }
    return ans;
}
struct C
{
    ll a;
    C() {}
    C(ll a) :a(a) {}
    C operator = (int a) { *this = C(a); return *this; }
    C operator + (const C &t) { return C(a + t.a >= mo ? (a + t.a - mo) : (a + t.a)); }
    C operator - (const C &t) { return C(a - t.a < 0 ? (a - t.a + mo) : (a - t.a)); }
    C operator * (const C &t) { return C(a*t.a%mo); }
};
C wn(int n, int f)
{
    return fpow(3, (mo - 1) / n >> 1);
}
C inv(int n)
{
    return fpow(n, mo - 2);
}
C a[maxn], b[maxn], c[maxn];
int g[maxn];
void NTT(C *a, int n, int f)
{
    for (int i = 0; i < n; i++)if (i > g[i])swap(a[i], a[g[i]]);
    for (int i = 1; i <= n; i <<= 1)
    {
        C w = wn(i, f), x, y;
        for (int j = 0; j < n; j += i + i)
        {
            C e; e = 1;
            for (int k = 0; k < i; e = e * w, k++)
            {
                x = a[j + k];
                y = a[j + k + i] * e;
                a[j + k] = x + y;
                a[j + k + i] = x - y;
            }
        }
    }
    if (f == -1)
    {
        C Inv = inv(n);
        for (int i = 0; i < n / 2; i++)swap(a[i], a[n - i]);
        for (int i = 0; i < n; i++)a[i] = a[i] * Inv;
    }
}
void conv(C *a, int n, C *b, int m, C *c)
{
    int k = 0, s = 2;
    while ((1 << k) < max(n, m) + 1)k++, s <<= 1;
    for (int i = 1; i < s; i++)g[i] = (g[i / 2] / 2) | ((i & 1) << k);
    NTT(a, s, 1);
    NTT(b, s, 1);
    for (int i = 0; i < s; i++)c[i] = a[i] * b[i];
    NTT(c, s, -1);
}
int main()
{
     int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 0; i <= n; i++)scanf("%lld", &a[i]);
    for (int i = 0; i <= m; i++)scanf("%lld", &b[i]);
    conv(a, n, b, m, c);
    for (int i = 0; i <= n + m; i++)printf("%lld ", c[i]);
    return 0;
}

第二个是double型的FFT,可以处理实数但是跑的会稍微慢一点

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1 << 18;
typedef complex<double> C;
C wn(int n, int f)
{
    return C(cos(acos(-1.0) / n), f*sin((acos(-1.0)) / n));
}
C inv(int n)
{
    return C(1.0 / n, 0);
}
C a[maxn], b[maxn], c[maxn];
int g[maxn];
void FFT(C *a, int n, int f)
{
    for (int i = 0; i < n; i++)if (i > g[i])swap(a[i], a[g[i]]);
    for (int i = 1; i < n; i <<= 1)
    {
        C w = wn(i, f), x, y;
        for (int j = 0; j < n; j += i + i)
        {
            C e; e = 1;
            for (int k = 0; k < i; e = e * w, k++)
            {
                x = a[j + k];
                y = a[j + k + i] * e;
                a[j + k] = x + y;
                a[j + k + i] = x - y;
            }
        }
    }
    if (f == -1)
    {
        C Inv = inv(n);
        for (int i = 0; i < n; i++)a[i] = a[i] * Inv;
    }
}
void conv(C *a, int n, C *b, int m, C *c)
{
    int k = 0, s = 2;
    while ((1 << k) < max(n, m) + 1)k++, s <<= 1;
    for (int i = 1; i < s; i++)g[i] = (g[i / 2] / 2) | ((i & 1) << k);
    FFT(a, s, 1);
    FFT(b, s, 1);
    for (int i = 0; i < s; i++)c[i] = a[i] * b[i];
    FFT(c, s, -1);
}
int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 0; i <= n; i++)scanf("%lf", &a[i]);
    for (int i = 0; i <= m; i++)scanf("%lf", &b[i]);
    conv(a, n, b, m, c);
    for (int i = 0; i <= n + m; i++)printf("%d ", (int)(c[i].real() + 0.5));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41955236/article/details/82016507