蒟蒻刚学 OI,四次 DFT WA 65 求助

P4245 【模板】任意模数多项式乘法

Aleph1022 @ 2020-01-03 08:55:55

拆系数然后通过系数共轭得到点值表达,为什么 65 \kel \kel \kel
怀疑是精度问题

代码:

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 1 << 18;
const long double pi = acos(-1);
const int W = 1 << 15;
int lena,lenb,mod,n;
int lg2[N + 5],rev[N + 5];
int ans[N + 5];
struct cp
{
    long double a,b;
    inline void operator+=(const cp &o)
    {
        a += o.a,b += o.b;
    }
    inline cp operator+(const cp &o) const
    {
        return (cp){a + o.a,b + o.b};
    }
    inline cp operator-(const cp &o) const
    {
        return (cp){a - o.a,b - o.b};
    }
    inline cp operator*(const cp &o) const
    {
        return (cp){a * o.a - b * o.b,a * o.b + b * o.a};
    }
    inline cp operator*(const double &o) const
    {
        return (cp){a * o,b * o};
    }
    inline cp operator~() const
    {
        return (cp){a,-b};
    }
} f[N + 5],g[N + 5],h[N + 5],a[N + 5],b[N + 5],rt[N + 5];
inline void init(int len)
{
    for(n = 1;n < len;n <<= 1);
    for(register int i = 2;i <= n;++i)
        lg2[i] = lg2[i >> 1] + 1;
    cp w = (cp){cos(2 * pi / n),sin(2 * pi / n)};
    rt[n >> 1] = (cp){1,0};
    for(register int i = (n >> 1) + 1;i <= n;++i)
        rt[i] = rt[i - 1] * w;
    for(register int i = (n >> 1) - 1;i;--i)
        rt[i] = rt[i << 1];
}
inline void fft(cp *a,int type,int n)
{
    type == -1 && (reverse(a + 1,a + n),1);
    int lg = lg2[n] - 1;
    for(register int i = 0;i < n;++i)
        rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << lg),
        i < rev[i] && (swap(a[i],a[rev[i]]),1);
    for(register int w = 2,m = 1;w <= n;w <<= 1,m <<= 1)
        for(register int i = 0;i < n;i += w)
            for(register int j = 0;j < m;++j)
            {
                cp t = rt[m | j] * a[i | j | m];
                a[i | j | m] = a[i | j] - t,a[i | j] += t;
            }
    if(type == -1)
        for(register int i = 0;i < n;++i)
            a[i].a /= n,a[i].b /= n;
}
int main()
{
    scanf("%d%d%d",&lena,&lenb,&mod),init(max(++lena,++lenb) << 1);
    int x;
    for(register int i = 0;i < lena;++i)
        scanf("%d",&x),f[i] = (cp){x / W,x % W};
    for(register int i = 0;i < lenb;++i)
        scanf("%d",&x),g[i] = (cp){x / W,x % W};
    fft(f,1,n),fft(g,1,n);
    for(register int i = 0;i < n;++i)
        h[i] = ~f[(n - i) % n];
    for(register int i = 0;i < n;++i)
        a[i] = f[i] * g[i],b[i] = g[i] * h[i];
    fft(a,-1,n),fft(b,-1,n);
    for(register int i = 0;i < n;++i)
    {
        long long ac = (a[i].a + b[i].a) / 2 + 0.5;
        long long bd = b[i].a - ac + 0.5;
        long long bcad = a[i].b + 0.5;
        ans[i] = ((ac % mod * W % mod * W % mod) % mod + (bcad % mod * W % mod) % mod + bd % mod) % mod;
    }
    for(register int i = 0;i < lena + lenb - 1;++i)
        printf("%d ",ans[i]);
}

by 神山识 @ 2020-01-03 08:57:01

qndjr


by 神山识 @ 2020-01-03 08:57:15

qndgxoi


by 雪颜 @ 2020-01-03 09:03:59

@alpha1022 我记得我WA50 -> 100就是改了输出的精度


by iostream @ 2020-01-03 09:42:37

每个单位根直接算应该可以,不要乘 w


by iostream @ 2020-01-03 09:43:12

for(int i=1;i<L>>1;i++)w[i+L/2]=Cp(cos(2*Pi*i/L),sin(2*Pi*i/L));

(我猜的)


by Aleph1022 @ 2020-01-03 09:53:07

@iostream 谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢谢
改了就过了 qwq


by pocafup @ 2020-01-03 11:23:41

%%%


by yummy @ 2020-01-03 12:00:27

Orz


by ImmortalWatcher @ 2020-01-09 16:44:57

THU二等的大佬你告诉我刚学OI??


|