【笔记】Big Integer - FFT Multiplication

这篇博客介绍了使用快速傅里叶变换(FFT)进行大整数乘法的方法,包括离散加权傅里叶变换和数论变换。通过FFT的时间复杂度分析,展示了如何优化计算速度。还讨论了在模素数下如何找到原根和乘法逆元,并应用到数论变换中。最后,提供了相关的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Discrete Weighted Transform FFT Multiplication

FFT时间复杂度时O(nlgn),当输入向量长度减半时时间复杂度为O(n/2lg(n/2)) < O((nlgn)/2),所需时间几乎减半。

调用FFT时,对于整数型向量,可以把向量的前半部分放入实部,后半部分放入虚部,比全部放入实部更快。

也就是对于长度为N的向量,0,1...N/2 - 1放入实部,N/2,N/2 + 1...N - 1放入虚部。在IDFT之后再调回来,注意虚部这时全部为负数。

/// <summary>
/// return Lo(data) + iHi(data), Lo(data) = data[0...i...n/2 - 1], Hi(data) = data[n/2...n/2+i...n-1]
/// </summary>
private static Complex[] Fold(int[] data)
{
    var result = new Complex[data.Length >> 1];
    for(var i = 0; i < result.Length; ++i)
    {
        result[i] = new Complex(data[i], data[result.Length + i]);
    }

    return result;
}

/// <summary>
/// return Real(data)...Imag(data), Real(data) = data[0...i...n-1].Real, Imag(data) = -data[0...i...n-1].Imaginary
/// </summary>
private static int[] UnFold(Complex[] data)
{
    var result = new int[data.Length << 1];
    for (var i = 0; i < data.Length; ++i)
    {
        result[i] = (int)Math.Round(data[i].Real);
        result[data.Length + i] = -(int)Math.Round(data[i].Imaginary);
    }

    return result;
}

当在DFT前对向量乘以一个系数,IDFT后再对结果乘以该系数的逆,就是离散加权傅里叶变换。加权向量a^N = -1 => a = e^-iπ/N。

/// <summary>
/// <paramref name="data"/>[i] *= <see cref="Math.E"/>^(-<see cref="Math.PI"/>*i/<paramref name="n"/>)
/// </summary>
private static void Weight(Complex[] data, int n)
{
    for(var i = 0; i < data.Length; ++i)
    {
        var theta = -Math.PI * i / n;
        data[i] *= new Complex(Math.Cos(theta), Math.Sin(theta));
    }
}

/// <summary>
/// <paramref name="data"/>[i] *= <see cref="Math.E"/>^(<see cref="Math.PI"/>*i/<paramref name="n"/>)
/// </summary>
private static void UnWeight(Complex[] data, int n)
{
    for (var i = 0; i < data.Length; ++i)
    {
        var theta = Math.PI * i / n;
        data[i] *= new Complex(Math.Cos(theta), Math.Sin(theta));
    }
}

CeilingPowerOf2参考《Hacker's Delight - Power-Of-2 Boundaries》。

Radix2Forward和Radix2Inverse参考《Cooley–Tukey FFT Algorithm - Iterative Edition》。

private static readonly int MASK = 0xFF;
/// <summary>
/// <see cr
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值