实现大数乘法,输入是两个字符串如
n1 = '340282366920938463463374607431768211456'
n2 = '340282366920938463463374607431768211456'
输出
'115792089237316195423570985008687907853269984665640564039457584007913129639936'
要求:不能使用对大数相乘有内建支持的语言;需要包含对输入字符串的合法性校验
一行,两个非负整数n1,n2,保证|n1|+|n2|<10000,其中|n|是n作为字符串的长度
输出n1*n2的结果
340282366920938463463374607431768211456 340282366920938463463374607431768211456
115792089237316195423570985008687907853269984665640564039457584007913129639936
给出的数据均是合法的,但仍建议您对输入的字符串进行合法性校验
string solve(string s, string t) {
int m=s.size(),n=t.size();
string result="0";
for(int i=m-1;i>=0;--i){
string cur="";
int carry=0;
for(int j=n-1;j>=0;--j){
int mul=(s[i]-'0')*(t[j]-'0')+carry;
cur=to_string(mul%10)+cur;
carry=mul/10;
if(j==0&&carry) cur=to_string(carry)+cur;
}
for(int j=0;j<m-i-1;++j){
cur=cur+"0";
}
result=strAdd(result,cur);
}
return result;
}
string strAdd(string s,string t){
int carry=0;
string result="";
for(int i=s.size()-1,j=t.size()-1;i>=0||j>=0||carry;--i,--j){
int x=i>=0?s[i]-'0':0;
int y=j>=0?t[j]-'0':0;
int sum =x+y+carry;
result=to_string(sum%10)+result;
carry=sum/10;
}
return result;
} import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.math.BigInteger;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] nums = br.readLine().trim().split(" ");
BigInteger num1 = new BigInteger(nums[0]);
BigInteger num2 = new BigInteger(nums[1]);
System.out.println(num1.multiply(num2).toString());
}
} 模拟竖式的代码如下 import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] nums = br.readLine().trim().split(" ");
System.out.println(multiply(nums[0], nums[1]));
}
private static String multiply (String num1, String num2) {
if(num1.equals("0") || num2.equals("0")) return "0";
String res = "0";
for(int i = num2.length() - 1; i >= 0; i --){
int carry = 0;
StringBuilder temp = new StringBuilder();
// 补0
for(int j = 0; j < num2.length() - 1 - i; j ++)
temp.append(0);
int n2 = num2.charAt(i) - '0';
for(int j = num1.length() - 1; j >= 0 || carry > 0; j --) {
int n1 = j < 0 ? 0 : num1.charAt(j) - '0';
temp.append((n1 * n2 + carry) % 10);
carry = (n1 * n2 + carry) / 10;
}
res = addStrings(res, temp.reverse().toString());
}
return res;
}
private static String addStrings(String num1, String num2) {
StringBuilder sum = new StringBuilder();
int carry = 0;
for(int i = num1.length() - 1, j = num2.length() - 1; i >= 0 || j >= 0 || carry > 0; i --, j --) {
int x = i < 0 ? 0 : num1.charAt(i) - '0';
int y = j < 0 ? 0 : num2.charAt(j) - '0';
sum.append((x + y + carry) % 10);
carry = (x + y + carry) / 10;
}
return sum.reverse().toString();
}
} import java.util.*;
public class Main {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param s string字符串 第一个整数
* @param t string字符串 第二个整数
* @return string字符串
*/
private static final int MAXN = 200100;
private Complex[] x1 = new Complex[MAXN];
private Complex[] x2 = new Complex[MAXN];
private int[] sum = new int[MAXN];
StringBuffer sb = new StringBuffer();
private static final double pi = Math.acos(-1.0);
private static class Complex{
private double x;
private double y;
public Complex(double x,double y){
this.x = x;
this.y = y;
}
public Complex add(Complex o1,Complex o2){
return new Complex(o1.x+o2.x,o1.y+o2.y);
}
public Complex subtract(Complex o1,Complex o2){
return new Complex(o1.x-o2.x,o1.y-o2.y);
}
public Complex multiply(Complex o1,Complex o2){
return new Complex(o1.x*o2.x-o1.y*o2.y,o1.y*o2.x+o1.x*o2.y);
}
}
public void change(Complex[] y,int len){
int i,j,k;
for(i=1,j=len/2;i<len-1;i++){
if(i<j){
Complex tem =y[i];
y[i] = y[j];
y[j] = tem;
}
k = len/2;
while (j>=k){
j-=k;
k/=2;
}
if(j<k) j+=k;
}
}
public void fft(Complex[] y,int len,int on){
change(y,len);
for(int h=2;h<=len;h<<=1){
Complex wn = new Complex(Math.cos(-on*2*pi/h),Math.sin(-on*2*pi/h));
for(int j=0;j<len;j+=h){
Complex w = new Complex(1,0);
for(int k=j;k<j+h/2;k++){
Complex u = y[k];
Complex t = w.multiply(w,y[k+h/2]);
y[k] = u.add(u,t);
y[k+h/2] = u.subtract(u,t);
w = w.multiply(w,wn);
}
}
}
if(on==-1){
for(int i=0;i<len;i++)
y[i].x/=len;
}
}
public String solve (String s, String t) {
int len1 = s.length();
int len2 = t.length();
int len=1;
while (len<len1*2||len<len2*2)
len<<=1;
for(int i=0;i<len1;i++)
x1[i] = new Complex(s.charAt(len1-i-1)-'0',0);
for(int i=len1;i<len;i++)
x1[i] = new Complex(0,0);
for(int i=0;i<len2;i++)
x2[i] = new Complex(t.charAt(len2-i-1)-'0',0);
for(int i=len2;i<len;i++)
x2[i] = new Complex(0,0);
fft(x1,len,1);
fft(x2,len,1);
for(int i=0;i<len;i++)
x1[i] = x1[i].multiply(x1[i],x2[i]);
fft(x1,len,-1);
for(int i=0;i<len;i++)
sum[i] = (int)(x1[i].x+0.5);
for(int i=0;i<len;i++){
sum[i+1]+=sum[i]/10;
sum[i]%=10;
}
len = len1+len2-1;
while (sum[len]<=0&&len>0)
len--;
for(int i=len;i>=0;i--)
sb.append(sum[i]);
return sb.toString();
}
public static void main(String[] args){
String s;
String t;
Scanner scanner = new Scanner(System.in);
s = scanner.next();
t = scanner.next();
System.out.println(new Main().solve(s,t));
}
} FFT板子
无力回天···········
/*
思路一:模拟乘法累加
按照乘法原理进行求解,将每一位相乘,
相加的结果保存到同一个位置,到最后才算进位。
3 2 5
X 9 8
-------------------------
(24)(16)(40)
(27)(18)(45)
-------------------------
(27)(42)(61)(40)
-------------------------
31 8 5 0
*/
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s1 = sc.next();
String s2 = sc.next();
//String s = "340282366920938463463374607431768211456";
char[] chars = s1.toCharArray();
int[] num1 = new int[s1.length()];
int k = 0;
for(char c:chars)
num1[k++] = Integer.parseInt(String.valueOf(c));
char[] chars2 = s2.toCharArray();
int[] num2 = new int[s2.length()];
k = 0;
for(char c:chars)
num1[k++] = Integer.parseInt(String.valueOf(c));
int[] res = new int[num1.length*2];
res = bigNumberMultiply(num1,num1);
for (int i=0;i<res.length;i++)
System.out.print(res[i]);
}
public static int[] bigNumberMultiply(int[] num1, int[] num2){
//分配空间,用来存储结果数字。num1 * num2 的结果长度肯定小于 num1+num2
int[] res = new int[num1.length + num2.length];
//先不考虑进位的问题,根据竖式的乘法运算,
//num1 的第i位 X num2的第j位,结果应该存放在第i+j的位置
for(int i=0; i<num1.length; i++){
for(int j=0; j<num2.length; j++){
//结果数组往后移一位(i+j+1),为最高位进位留出空间
//
res[i+j+1] = res[i+j+1] + num1[i]*num2[j];
}
}
//单独处理进位问题
for(int k = res.length-1; k>0; k--){
if(res[k] > 10){
//进位
res[k-1] = res[k-1] + res[k]/10;
//当前位取个位数
res[k] = res[k]%10;
}
}
return res;
}
} #include <bits/stdc++.h>
using namespace std;
int main(){
string a, b;
cin>>a>>b;
int n=a.length(), m=b.length();
int s[n+m];
memset(s, 0, sizeof(s));
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
s[n+m-i-j-2] += (a[i]-'0')*(b[j]-'0');
for(int i=0,c=0;i<n+m;i++){
s[i] += c;
c = s[i]/10;
s[i] %= 10;
}
bool p = true;
for(int i=n+m-1;i>=0;i--){
if(p){
if(i && !s[i])
continue;
else{
p = false;
cout<<s[i];
}
}else
cout<<s[i];
}
cout<<endl;
return 0;
} //需要考虑的特殊用例是:输入字符串为0||输入的最高位有0||得数前面的0要省略
#include <bits/stdc++.h>
using namespace std;
string strmul(string a,string b){
if(a.empty()||b.empty()||a[0]=='0'&&a.size()==1||b[0]=='0'&&b.size()==1)
return "0";
string str(a.size()+b.size(),'0');
int index,len=str.size()-1;
for(int i=a.size()-1;i>=0;i--,len--){
index=len;
int up=0;
for(int j=b.size()-1;j>=0;j--,index--){
int ans=(a[i]-'0')*(b[j]-'0');
int temp=ans%10+up+str[index]-'0';
str[index]=temp%10+'0'; //保留个位
up=ans/10 + temp/10; //保留进位
}
if(up!=0)
str[index]=up+'0';
}
int k=0;
while(str[k]=='0')
k++;
return str.substr(k);
}
int main(){
string a,b;
cin>>a>>b;
cout<<strmul(a,b);
return 0;
} #include<stdio.h>
#include<string.h>
#define LEN 10000
void reverse(int a[],int n);
void copy(const char *str,int a[]);
int main()
{
char str1[LEN];
char str2[LEN];
scanf("%s%s",str1,str2);
int a = strlen(str1);
int b = strlen(str2);
int arr1[LEN] = {0};
copy(str1,arr1);
int arr2[LEN] = {0};
copy(str2,arr2);
reverse(arr1,a);
reverse(arr2,b);
int res[LEN] = {0};
int i;
for(i = 0;i < a;++i){
for(int j = 0;j < b;++j){
res[i + j] += arr1[i] * arr2[j];
res[i + j + 1] += res[i + j] / 10;
res[i + j] %= 10;
}
}
for(i = LEN - 1;res[i] == 0 && i;--i);
for(;i >= 0;--i){
printf("%d",res[i]);
}
return 0;
}
void reverse(int a[],int n)
{
for(int i = 0,j = n - 1;i < j;++i,--j){
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
void copy(const char *str,int a[])
{
int i = 0;
while(*str){
a[i++] = *str - '0';
str++;
}
}
Java 版本,参考了几位大佬的回答。
//package cn.practice.niuke;
import java.util.Scanner;
/**
* 大数相乘。
* 给出的数据均是合法的,但仍建议您对输入的字符串进行合法性校验
* 远远超出 longest.
*/
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s1 = scanner.next();
String s2 = scanner.next();
// 先不做校验。
int sumLen = s1.length() + s2.length();
int[] res = new int[sumLen];
for(int i = 0; i< s1.length(); i++) {
int num1 = s1.charAt(s1.length() -1 - i ) - '0';
for(int j = 0; j< s2.length(); j++) {
int num2 = s2.charAt(s2.length() -1 - j) - '0';
res[i +j ] += num1 * num2;
}
}
for(int i = 0; i< res.length - 1; i++) {
if(res[i] >= 10) {
res[i+1] += res[i] / 10;
res[i] %= 10;
}
}
int i = res.length -1;
for(; i> 0 && res[i] == 0; i--) {} // 去除结果前面的 0
StringBuilder sb = new StringBuilder();
for(; i>=0; i--) {
sb.append(res[i]);
}
System.out.println(sb.toString());
}
}
#include <bits/stdc++.h>
using namespace std;
int main()
{
string st1,st2;
cin>>st1;
cin>>st2;
int n = st1.size(),m = st2.size();
int a[n + m];
fill(a, a + n + m, 0);
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
a[n + m - i - j - 2] += (st1[i] - '0') * (st2[j] - '0');
for (int i = 0; i < n + m - 1; ++i)
{
a[i + 1] += a[i] / 10;
a[i] %= 10;
}
int r = n + m - 1;
for (; r && !a[r]; r--);
for (;r >= 0;--r)
cout<<a[r];
cout<<endl;
return 0;
}
#include<cstdio>
(802)#include<cstring>
int main()
{
char str[10000];
int a[10000]={0},b[10000]={0};
scanf("%s",str);
int len1=strlen(str);
for(int i=0;i<len1;i++)
a[i]=str[len1-i-1]-'0';
scanf("%s",str);
int len2=strlen(str);
for(int i=0;i<len2;i++)
b[i]=str[len2-i-1]-'0';
int carry=0,i,c[10000]={0},s;
for(i=0;i<len1;i++)
{
s=i;
for(int j=0;j<len2;j++)
{
int temp=a[i]*b[j]+carry;
c[s]+=temp%10;
carry=temp/10;
if(c[s]>=10)
{
c[s]=c[s]%10;
carry++;
}
s++;
}
while(carry!=0)
{
c[s++]=carry%10;
carry=carry/10;
}
}
for(int j=s-1;j>=0;j--)
printf("%d",c[j]);
return 0;
} function bitIntMultiply(num1, num2) {
num1 = toStringArray(num1);
num2 = toStringArray(num2);
let result = [];
// 乘数,假如为11
for (let i = 0; i < num1.length; i++) {
// 被乘数,假如为111,如将11的1与111的每一位相乘然后存入
for (let j = 0; j < num2.length; j++) {
// 将结果添加到对应的位数上,如果该位数上存在则继续加,不存在则写入
result[i + j] = result[i + j] ?
result[i + j] + num1[i] * num2[j] :
num1[i] * num2[j];
}
}
for (let i = 0; i < result.length; i++) {
// 确认是否进位,仅在进位时增加数组长度
let carry = Math.floor(result[i] / 10);
if (carry) {
result[i + 1] = result[i + 1] ?
result[i + 1] + carry :
carry;
}
result[i] = result[i] % 10;
}
return result.reverse().join('');
function toStringArray(num) {
return String(num).split('').reverse();
}
} 可以通过93.3%,很不爽!
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string multiply(string num1, string num2) {
int len1 = num1.size(),len2 = num2.size();
string res(len1 + len2, '0');
for (int i = len2 - 1; i >= 0; i--) { //从个位开始。注意:数组是从高位到低位存储的,i+j相对i+j+1才是高位!
for (int j = len1 - 1; j >= 0; j--) {
int temp = (res[i + j + 1] - '0') + (num1[j] - '0')*(num2[i] - '0');//res[i + j + 1] - '0',有可能之前进位了,而且最多只会进位影响一位
res[i + j + 1] = temp % 10 + '0';//当前位.这里是等于,所以要加‘0’
res[i + j] += temp / 10; //前一位加上进位!!!res[i+j]已经初始化为'0',加上int类型自动转化为char,所以此处不加'0'
}
}
//去除首位'0'
for (int i = 0; i<len1 + len2; i++) //从高位到低位找0
if (res[i] != '0')
return res.substr(i);//从第一个不是0的数截取
return "0";
}
int main() {
string num1,num2;
cin >> num1 >> num2;
cout << multiply(num1, num2)<<endl;
return 0;
} Java似乎没法通过。。。。代码如下
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String big1 = sc.nextLine(); String big2 = sc.nextLine(); int length1 = big1.length(); int length2 = big2.length(); if (length1 == 0 && length2 == 0){ System.out.println("0"); } else { int[] res = new int[length1 + length2]; for (int i = 0; i < length1; i++) { int num1 = big1.charAt(length1 - 1 - i) - '0'; for (int j = 0; j < length2 ;j++) { int num2 = big2.charAt(length2 - 1 - j) - '0'; int tempres = num1 * num2; res[i + j] += tempres; } } for (int i = 0; i < length1 + length2; i++) { if (res[i] > 10){ res[i+1] += (res[i] / 10); res[i] %= 10; } } StringBuilder sb = new StringBuilder(); for (int i = length1 + length2 - 1; i >= 0 ; i--) { sb.append(res[i]); } System.out.println(Integer.parseInt(sb.toString())); } }
}