题目:给出两个n位10进制整数x和y,你需要计算x*y。($n \leq 60000$)

分析:

两个正整数的相乘可以视为两个多项式的相乘,

例如 $15 \times 16 = 240$,

可写成 $(5+x)*(6+x) = 30 + 11x + x^2$,$x=10$

这样得到多项式 $A(x)$ 和 $B(x)$,并且能用FFT求出 $C(x)=A(x)B(x)$,

怎么得到最终结果,我们要将 $x=10$ 代入吗?

$n$ 这么大,遍历一遍也没有这么大的数据类型能存下,其次,这也不是必要的。

$x=10$ 是 $C(x)$ 已经相当于十进制,我们模拟一下进位就可以了。

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int MAXN = * + ;
inline int read() {
char c = getchar(); int x = , f = ;
while (c < '' || c > '') {if (c == '-')f = -; c = getchar();}
while (c >= '' && c <= '') {x = x * + c - ''; c = getchar();}
return x * f;
}
const double Pi = acos(-1.0);
const double Eps = 1e-;
double ccos[MAXN], ssin[MAXN];
struct complex {
double x, y;
complex (double xx = , double yy = ) {x = xx, y = yy;}
} a[MAXN], b[MAXN];
complex operator + (complex a, complex b) { return complex(a.x + b.x , a.y + b.y);}
complex operator - (complex a, complex b) { return complex(a.x - b.x , a.y - b.y);}
complex operator * (complex a, complex b) { return complex(a.x * b.x - a.y * b.y , a.x * b.y + a.y * b.x);} //不懂的看复数的运算那部分
void fast_fast_tle(int limit, complex *a, int type) {
if (limit == ) return ; //只有一个常数项
complex a1[limit >> ], a2[limit >> ];
for (int i = ; i < limit; i += ) //根据下标的奇偶性分类
a1[i >> ] = a[i], a2[i >> ] = a[i + ];
fast_fast_tle(limit >> , a1, type);
fast_fast_tle(limit >> , a2, type);
complex Wn = complex(ccos[limit] , type * ssin[limit]), w = complex(, );
//complex Wn = complex(cos(2.0 * Pi / limit) , type * sin(2.0 * Pi / limit)), w = complex(1, 0);
//Wn为单位根,w表示幂
for (int i = ; i < (limit >> ); i++, w = w * Wn) //这里的w相当于公式中的k
{
complex tmp = w * a2[i];
a[i] = a1[i] + tmp;
a[i + (limit >> )] = a1[i] - tmp; //利用单位根的性质,O(1)得到另一部分
}
} char s[MAXN];
int res[MAXN]; int main() {
int N = read();
scanf("%s", s);
for (int i = ; i < N; i++) a[i].x = s[N--i]-'';
scanf("%s", s);
for (int i = ; i < N; i++) b[i].x = s[N--i]-''; //for(int i = 0;i < N;i++) printf("%f ", a[i]); int limit = ; while (limit <= *N) limit <<= ; for(int i = ;i <= limit;i++)
{
ccos[i] = cos(2.0 * Pi / i);
ssin[i] = sin(2.0 * Pi / i);
} fast_fast_tle(limit, a, );
fast_fast_tle(limit, b, );
//后面的1表示要进行的变换是什么类型
//1表示从系数变为点值
//-1表示从点值变为系数
//至于为什么这样是对的,可以参考一下c向量的推导过程,
for (int i = ; i <= limit; i++)
a[i] = a[i] * b[i];
fast_fast_tle(limit, a, -); for(int i = ;i <= *N;i++) res[i] = int(a[i].x/limit+0.5); int tmp = ; //进位
for(int i = ;i <= *N;i++)
{
res[i] += tmp;
tmp = res[i] / ;
res[i] = res[i] % ;
} bool flag = false;
for (int i = *N; i >= ; i--)
{
if(res[i]) flag = true; //注意处理前导0,题干有说
if(flag) printf("%d", res[i]); //按照我们推倒的公式,这里还要除以n
}
return ;
}

【模板】A*B Problem(FFT快速傅里叶)的更多相关文章

  1. FFT快速傅里叶模板

    FFT快速傅里叶模板…… /* use way: assign : h(x) = f(x) * g(x) f(x):len1 g(x):len2 1. len = 1; while(len < ...

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

    Description 给出两个n位10进制整数x和y,你需要计算x*y. Input 第一行一个正整数n. 第二行描述一个位数为n的正整数x. 第三行描述一个位数为n的正整数y. Output 输出 ...

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

    模板 嗯 做多项式乘法,进位 没了 #include<cmath> #include<cstdio> #include<cstring> #include<a ...

  4. Luogu P1919 【模板】A*B Problem升级版(FFT快速傅里叶_FFT

    这其实就是一道裸的FFT 核心思想:把两个数拆成两个多项式用FFT相乘,再反序输出 py解法如下: input() print(int(input())*int(input())) 皮一下hihi f ...

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

    题目来源 吐槽下P3803都是紫题... 真心好写,本想一遍过的...但是 我真是太菜了... #include<bits/stdc++.h> using namespace std; ; ...

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

    题目描述 给出两个n位10进制整数x和y,你需要计算x*y. 输入输出格式 输入格式: 第一行一个正整数n. 第二行描述一个位数为n的正整数x. 第三行描述一个位数为n的正整数y. 输出格式: 输出一 ...

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

    题目描述 给出两个n位10进制整数x和y,你需要计算x*y. 输入输出格式 输入格式: 第一行一个正整数n. 第二行描述一个位数为n的正整数x. 第三行描述一个位数为n的正整数y. 输出格式: 输出一 ...

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

    题目描述 给出两个 $n$ 位10进制数x和y,求x*y(详见 洛谷P1919) 分析 假设已经学会了FFT/NTT. 高精度乘法只是多项式乘法的特殊情况,相当于$x=10$ 时. 例如n=3,求12 ...

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

    题目链接:洛谷.BZOJ2179 //将乘数拆成 a0*10^n + a1*10^(n-1) + ... + a_n-1的形式 //可以发现多项式乘法就模拟了竖式乘法 所以用FFT即可 注意处理进位 ...

随机推荐

  1. Haffman编码

    Huffman树又称为最优树,是一种带权路径最短的树. 一.带权路径 在一棵树中我们把一个节点到另一个节点之间的通路叫做路径,在路径中每经过一个节点路径的长度就加一.如果对一个节点附上权值,则该节点的 ...

  2. Jmeter相关参数

    一.线程组 线程组主要包含三个参数:线程数.准备时长(Ramp-Up Period(in seconds)).循环次数. 线程数:虚拟用户数.一个虚拟用户占用一个进程或线程.设置多少虚拟用户数在这里也 ...

  3. C# 练习题 判断1至输入数值之间有多少个素数,并输出所有素数。

    题目:判断1至输入数值之间有多少个素数,并输出所有素数.1.程序分析:判断素数的方法:用一个数分别去除2到当前数-1,如果能被整除,则表明此数不是素数,反之是素数. class Program { / ...

  4. 在Centos中安装.net core SDK

    在Linux中运行.net core 项目必须要有.net core SDK 环境.之前配置过几次,但由于没有做总结.过了几天又配置的时候 感觉特别陌生,今天就记录一次.net core SDK 的安 ...

  5. 如何在CentOS / RHEL 7上启用IPv6

    默认情况下,在RHEL / CenOS 7系统上启用IPv6.因此,如果故意在系统上禁用IPv6,则可以通过以下任一方法重新启用它. 1.在内核模块中启用IPv6(需要重启)2.使用sysctl设置启 ...

  6. 类中__iter__与__next__的说明

    class Fab(object): def __init__(self ,max ): self.max =max self.n =0 self.a=0 self.b =1 def __iter__ ...

  7. java中四种权限修饰符区别

    总的概括:public > protected > (default) > private 细分见下表格: 权限修饰符 public protected (default) priv ...

  8. Matlab工厂模式

    工厂模式定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类.工厂模式主要分为简单工厂模式.工厂方法模式以及抽象工厂模式. Obj.m classdef Obj ...

  9. 【转】【Salesforce】salesforce 零基础学习(十七)Trigger用法

    看本篇之前可以相应阅读以下Trigger相关文章: 1.https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigge ...

  10. misc_register杂项设备

    include/linux/miscdevice.h 这些字符设备不符合预先确定的字符设备范畴 设备主设备号10 struct miscdevice { int minor; //次设备号(如果设置为 ...