实现大数乘法,输入是两个字符串如
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())); } }
}