整数乘法,你能做多少位?

整数相乘

问题:在几秒内求出两个正整数的乘积?

这个简单的问题,你能做到哪一步?

如果两个5位整数相乘,这样就可以了

#include <cstdio>

int main() {
    int a, b;
    scanf("%d%d", &a, &b);
    printf("%d\n", a*b);
    return 0;
}

但如果要计算10位的整数相乘,那就得改成这样了

#include <cstdio>

int main() {
    long long a, b;
    scanf("%lld%lld", &a, &b);
    printf("%lld\n", a*b);
    return 0;
}

如果整数上百位千位了,那就要这样了

#include <iostream>
#include <string>
#include <vector>
#include <stdlib.h>
using namespace std;

void reverse_data(string &data);
string multiply(string numa, string numb);

void reverse_data(string &data) {
    char temp = '0';
    int start=0;
    int end=data.size()-1;
    while (start < end) {
        temp = data[start];
        data[start++] = data[end];
        data[end--] = temp;
    }
}

string multiply(string numa, string numb) {
    reverse_data(numa);
    reverse_data(numb);
    int i, j, c = 0;
    string temp(numa.size()+numb.size(),'0');
    for (i=0;i<numa.size();i++) {
        for (j=0;j<numb.size();j++) {
            c+=temp[i+j]-'0'+(numa[i]-'0')*(numb[j]-'0');
            temp[i+j]=(c%10)+'0';
            c=c/10;
        }
        while(c) {
            temp[i+j++]+=c%10;
            c=c/10;
        }
    }
    for (i=temp.size()-1;i>=0;i--) {
        if (temp[i] != '0') {
            break;
        }
    }
    temp = i >= 0 ? temp.substr(0, i+1): "0";
    reverse_data(temp);
    return temp;
}

int main() {
    string a,b;
    cin >>a >>b;
    string result = multiply(a, b);
    cout << result <<endl;
    return 0;
}

而要相乘的整数达到上百万位的时候,就得这样了。

#include <stdio.h>
#include <math.h>
#include <string.h>
const int BASE = 100000;
const int N_DIGIT = 5;
const int N = 32768*16;
const double PI = acos(-1.0);

struct plex {
    double real, imag;
};

plex omega[N >> 1];
plex a[N];
plex b[N];

char s[1000003];
int d[N], len;

void bitReverse(plex a[]) {
    int i, j = 1, k;
    plex t;
    for (i = 1; i < len; ++ i)
    {
        if (i < j)
        {
            t.real = a[j - 1].real;
            t.imag = a[j - 1].imag;
            a[j - 1].real = a[i - 1].real;
            a[j - 1].imag = a[i - 1].imag;
            a[i - 1].real = t.real;
            a[i - 1].imag = t.imag;
        }
        k = len >> 1;
        while (k < j)
        {
            j -= k;
            k >>= 1;
        }
        j += k;
    }
}

void calOmega() {
    double unit = 2 * PI / len;
    int n = len >> 1;
    for (int i = 0; i < n; ++ i)
    {
        double t = unit * i;
        omega[i].real = cos( t );
        omega[i].imag = sin( t );
    }
}

void fft(plex a[], bool inverse = false){
    bitReverse( a );

    int s = len >> 1;
    int m, k, j;
    int up, t, step;
    int i1, i2;
    plex tmp;

    if ( inverse ) {
        for (j = 0; j < s; ++ j)
            omega[j].imag = - omega[j].imag;
    }
    s = 1;
    for (m = 2; m <= len; m <<= 1) {
        up = m >> 1, t = len >> s; // 2^(log2(n) - s) != n - 2^s !!!!!!!
        for (k = 0; k < len; k += m) {
            step = 0;
            for (j = 0; j < up; ++ j) {
                i1 = k + j;
                i2 = i1 + up;
                tmp.real = omega[step].real * a[i2].real - omega[step].imag * a[i2].imag;
                tmp.imag = omega[step].real * a[i2].imag + omega[step].imag * a[i2].real;
                a[i2].real = a[i1].real - tmp.real;
                a[i2].imag = a[i1].imag - tmp.imag;
                a[i1].real += tmp.real;
                a[i1].imag += tmp.imag;
                step += t;
            }
        }
        ++ s;
    }
    if ( inverse ) {
        double t = 1.0 / len;
        for (j = 0; j < len; ++ j)
            a[j].real *= t;
    }
}

int convert(int d[], char s[])
{
    int sLen = strlen( s );
    int dLen = ((sLen - 1) / N_DIGIT) + 1, i = 0, n;
    char *pRight = s + sLen - 1, *pLeft = pRight - (N_DIGIT - 1);
    memset(d, 0, sizeof(int) * dLen);


    while (i < dLen && pRight >= s)
    {
        if (pLeft < s) pLeft = s;
        n = 0;
        while (pLeft <= pRight)
        {
            n = n * 10 + (*pLeft & 15);
            ++ pLeft;
        }
        d[i ++] = n;
        pRight -= N_DIGIT;
        pLeft = pRight - (N_DIGIT - 1);
    }
    return dLen;
}

bool init() {
    int i, j;
    if (scanf("%s", s) != 1)
        return false;
    int aLen = convert(d, s); //length of a
    for (i = 0; i < aLen; ++ i) {
        a[i].real = d[i];
        a[i].imag = 0;
    }

    scanf("%s", s);
    int bLen = convert(d, s);
    for (j = 0; j < bLen; ++ j)
    {
        b[j].real = d[j];
        b[j].imag = 0;
    }

    len = 1; //length of product who uses int
    while (len < aLen + bLen) len <<= 1;

    memset(a + i, 0, sizeof(plex) * (len - i));
    memset(b + j, 0, sizeof(plex) * (len - j));

    calOmega();
    return true;
}

void mul()
{
    for (int i = 0; i < len; ++ i)
    {
        double real = a[i].real * b[i].real - a[i].imag * b[i].imag;
        double imag = a[i].real * b[i].imag + a[i].imag * b[i].real;
        a[i].real = real;
        a[i].imag = imag;
    }
}

void print() {
    double carry = 0, t;
    static char format[10];
    int i;

    for (i = 0; i < len; ++ i) {
        t = carry + a[i].real;
        carry = floor((t + 0.5) / BASE);
        d[i] = int(t - carry * BASE + 0.5);
    }
    for (i = len - 1; i > 0 && d[i] == 0; -- i);
    sprintf(format, "%%.%dd", N_DIGIT);
    printf("%d", d[i]);
    for (-- i; i >= 0; -- i)
        printf(format, d[i]);
    printf("\n");
}

int main() {
    int inn; scanf( "%d", &inn );
    while ( inn-- ) {
        init();
        fft( a );
        fft( b );
        mul();
        fft(a, true);
        print();
    }
    return 0;
}

作者原创,转载请注明出处

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容