洛谷.1919.[模板]A乘B Problem升级版(FFT)

题目链接:洛谷BZOJ2179

//将乘数拆成 a0*10^n + a1*10^(n-1) + ... + a_n-1的形式
//可以发现多项式乘法就模拟了竖式乘法 所以用FFT即可 注意处理进位
//n位*n位最多就只有2n位了
//论putchar的速度。。还是快的
#include <cmath>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
const int N=6e4+5;
const double PI=acos(-1);

int n,ans[N<<1];
struct Complex
{
    double x,y;
    Complex(double xx=0,double yy=0) {x=xx, y=yy;}
    Complex operator + (const Complex &a) {return Complex(x+a.x, y+a.y);}
    Complex operator - (const Complex &a) {return Complex(x-a.x, y-a.y);}
    Complex operator * (const Complex &a) {return Complex(x*a.x-y*a.y, x*a.y+y*a.x);}
}A[N*3],B[N*3];

inline void read(Complex *a)
{
    int cnt=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);a[cnt++].x=(double)(c-'0'),c=gc());
}
void Fast_Fourier_Transform(Complex *a,int lim,int opt)
{
    for(int j=0,i=0; i<lim; ++i)
    {
        if(i>j) std::swap(a[i],a[j]);
        for(int l=lim>>1; (j^=l)<l; l>>=1);
    }
    for(int i=2; i<=lim; i<<=1)
    {
        int mid=i>>1;
        Complex Wn(cos(2.0*PI/i),opt*sin(2.0*PI/i)),t;
        for(int j=0; j<lim; j+=i)
        {
            Complex w(1,0);
            for(int k=0; k<mid; ++k,w=w*Wn)
                a[j+mid+k]=a[j+k]-(t=w*a[j+mid+k]),
                a[j+k]=a[j+k]+t;
        }
    }
}

int main()
{
    scanf("%d",&n);
    read(A), read(B);
    std::reverse(A,A+n), std::reverse(B,B+n);
    int lim=1;
    while(lim <= n<<1) lim<<=1;
    Fast_Fourier_Transform(A,lim,1);
    Fast_Fourier_Transform(B,lim,1);
    for(int i=0; i<=lim; ++i) A[i]=A[i]*B[i];
    Fast_Fourier_Transform(A,lim,-1);
    int t=n<<1;
    for(int i=0; i<=t; ++i) ans[i]=(int)(A[i].x/lim+0.5);
    for(int i=0; i<t; ++i) ans[i+1]+=ans[i]/10, ans[i]%=10;
    while(!ans[t] && t) --t;
    while(~t) putchar(ans[t--]+'0');

    return 0;
}

原文地址:https://www.cnblogs.com/SovietPower/p/8447700.html

时间: 2024-10-13 11:10:00

洛谷.1919.[模板]A乘B Problem升级版(FFT)的相关文章

P1919 【模板】A*B Problem升级版(FFT快速傅里叶)

P1919 [模板]A*B Problem升级版(FFT快速傅里叶) 思路还是挺简单的. 输入的2个数 \(a=\overline{a_n a_{n-1} a_{n-2}\cdots a_{0}}\) , \(b=\overline{b_m b_{m-1} b_{m-2}\cdots b_{0}}\) 直接把 \(a_i\) 和 \(b_i\) 看做多项式 A 和 B 的系数,做多项式乘法即可.因为 a ,b 可以看做以 \(a_i,b_i\) 为系数,自变量为10的多项式的值,乘完后的多项式的

【C++】最近公共祖先LCA(Tarjan离线算法)&amp;&amp; 洛谷P3379LCA模板

1.前言 首先我们介绍的算法是LCA问题中的离线算法-Tarjan算法,该算法采用DFS+并查集,再看此算法之前首先你得知道并查集(尽管我相信你如果知道这个的话肯定是知道并查集的),Tarjan算法的优点在于相对稳定,时间复杂度也比较居中,也很容易理解(个人认为). 2.思想 下面详细介绍一下Tarjan算法的思想: 1.任选一个点为根节点,从根节点开始. 2.遍历该点u所有子节点v,并标记这些子节点v已被访问过. 3.若是v还有子节点,返回2,否则下一步. 4.合并v到u上. 5.寻找与当前点

AC自动机(附洛谷P3769模板题)

首先,介绍一下AC自动机(Aho-Corasick automaton),是一种在一个文本串中寻找每一个已给出的模式串的高效算法. 在学习AC自动机之前,你需要先学习Trie树和KMP算法,因为AC自动机正式利用并结合了两者的思想. 说到实际的不同,其实AC自动机只是在Trie树上引入了一个类似KMP中next数组的东西叫做Fail指针. 对于每一个节点,Fail指针指向该节点所代表的字符串中,次长的.在Trie树中存在的后缀(因为最长的在Trie树种存在的后缀就是其本身)所代表的节点. 举例:

洛谷P3375 [模板]KMP字符串匹配

To 洛谷.3375 KMP字符串匹配 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了. 输入输出格式 输入格式: 第一行为一个字符串,即为s1(仅包含大写字母) 第二行为一个字符串,即为s2(仅包含大写字母) 输出格式: 若干行,每行包含一个整数,表示s2在s1中出现的位置 接下来1行,包括length(s2)个整

洛谷.3803.[模板]多项式乘法(FFT)

题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. #include <cmath> #include <cctype> #include <cstdio> #include <algorithm> #define gc() getchar() const int N=1e6+5; const double PI=acos(-1); int n,m; struct Complex { double

洛谷 [P2483] [模板] k短路

人生中的第一道黑题... 其实就是k短路模板 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <cstdlib> #include <queue> using namespace std; const int MAXN=400005; int init(){ int

[Luogu 1919]【模板】A*B Problem升级版(FFT快速傅里叶)

Description 给出两个n位10进制整数x和y,你需要计算x*y. Input 第一行一个正整数n. 第二行描述一个位数为n的正整数x. 第三行描述一个位数为n的正整数y. Output 输出一行,即x*y的结果.(注意判断前导0) Sample Input 134 Sample Output 12 HINT n<=60000 题解 A*B Problem.和 A+B Problem 一样简单. 1 input() and print(int(input()) * int(input()

洛谷P3805 [模板]Manacher算法 [manacher]

题目传送门 题目描述 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 字符串长度为n 输入输出格式 输入格式: 一行小写英文字符a,b,c...y,z组成的字符串S 输出格式: 一个整数表示答案 输入输出样例 输入样例#1: aaa 输出样例#1: 3 说明 字符串长度len <= 11000000 分析:manacher算法模板,算法分析就不具体讲了,five20大佬讲的挺好的,可以参照一下他的博客. Code: 1 //It is made by Ho

并查集模板(洛谷——【模板】并查集)

#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=10010; int fa[maxn],n,m; void init(){ for(int i=1;i<=n;i++)fa[i]=i; } int find(int x){ if(fa[x]==x)return x; return fa