vector
Luogu original topic https://www.luogu.com.cn/problem/P1009
This topic requires high-precision factorial writing, but I haven't learned it yet. I picked up all kinds of materials and online classes from the Internet and found that before learning high precision, I need to know the container vector.
What is a vector
vector is a sequential container that encapsulates dynamic size arrays and belongs to C++STL. You can simply think. vector is a dynamic array that can store any type.
Using vector
To use vector, you need to add at the beginning of the file
#include< vector >
using namespace std;
Original link: https://blog.csdn.net/qq_38654981/article/details/81907134
https://blog.csdn.net/w_linux/article/details/71600574
Initialization of vector:
- Vector < type > identifier / / vector a
- Vector < type > identifier (maximum capacity) / / vector (10)
- Vector < type > identifier (maximum capacity, initial all values) / / vector (10,1)
- int b[7]={1,2,3,4,5,9,8}; vector a(b,b+7); // Get initial value from array
- vector< vector< int> >v; Two dimensional vector / / the outermost < > here must have a space. Otherwise, it cannot pass under the older compiler
- vector a(b); // Use B vector to create a vector, and assign global replicability
vector function set
https://blog.csdn.net/w_linux/article/details/71600574
High precision calculation
After learning vector, start learning high-precision calculation
In fact, high-precision computing is to store big data in a string for manual operation and re storage. The principle is roughly the same and the algorithm is different.
High precision addition
#include <iostream> //< vector > comes with a size function to find the length #include <vector> using namespace std; //Array length + 10 prevents boundary problems const int N=1e6+10; //Write a method that returns the vector type //The address character is taken here because the reference type is faster //C=A+B vector<int> add(vector<int> &A,vector<int> &B){ vector<int> C; int t =0;//This is a carry and is used to store data at the same time for (int i=0;i<A.size()||i<B.size();i++){ if(i<A.size()) t+=A[i]; if(i<B.size()) t+=B[i]; //The current bit can only store single digits of data t C.push_back(t%10); //Let t divide by 10 t/=10; } //If t is still several at this time, enter 1 if(t) C.push_back(1); return C; } int main(){ //The number is too long to read with string string a,b; vector<int>A,B; cin>>a>>b; //a="123456" for(int i=a.size()-1;i>=0;i--)A.push_back(a[i]-'0'); //Store in reverse order / / characters become integers minus' 0 ' for(int i=b.size()-1;i>=0;i--)B.push_back(b[i]-'0'); auto C = add(A,B); //Reverse order output for(int i=C.size()-1;i>=0;i--) printf("%d",C[i]); return 0; }
High precision subtraction
High precision subtraction and addition are mainly input and output in the main function. There is no difference. Therefore, for convenience, only function template fragments are put in.
vector<int> sub(vector<int> &A, vector<int> &B) { vector<int> C; for (int i = 0, t = 0; i < A.size(); i ++ ) { //t is used to store data t = A[i] - t; //Maybe there's a borrow space in front if (i < B.size()) t -= B[i]; C.push_back((t + 10) % 10);//t+10 because t-B[i] may be negative //If T < 0, record and borrow 1 from the high order. When t = a [i] - t = 1, the high order number decreases by 1 if (t < 0) t = 1; else t = 0; } while (C.size() > 1 && C.back() == 0) C.pop_back();//Judge whether the highest bit is 0 return C; }
High precision multiplied by low precision
High precision multiplication is different from the usual multiplication formula. Usually, we do multiplication, such as 123 * 12, which is 123 * 2 + 123 * 10.
And high-precision multiplication, such as 123 * 12
3 * 12 = 36, carry 3, and the last bit is 6.
2 * 12 + 3 = 27, the penultimate bit of carry 2 is 7.
1 * 12 + 2 = 14, carry 1, and the penultimate digit is 4.
0 * 12 + 1 = 1, the first digit is 1.
Combined to 1476.
The code implementation is as follows:
#include <iostream> //< vector > comes with a size function to find the length #include <vector> using namespace std; //Array length + 10 prevents boundary problems const int N=1e6+10; //Write a method that returns the vector type //The address character is taken here because the reference type is faster vector<int> mul(vector<int> &A,int b) { vector<int> C; if (b==0){ //Because it is a string type, 00000 will be output at * 0 without if judgment C.push_back(0); return C; } int t =0; for (int i =0;i<A.size();i++){ t+=A[i]*b; //t=t+A[i]*b the first t = represents the data, and T + of T + represents the carry of the previous operation C.push_back(t%10); //Single digits of t t=t/10; //Carry of t } if (t) C.push_back(t); //Add carry return C; } int main(){ //a the number is too long, read it with string, b can read it directly string a; int b; //Save a to vector vector<int> A; cin>>a>>b; //Deposit from low position for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0'); auto C = mul(A,b); //Output from the end of the vector for(int i =C.size()-1;i>=0;i--) printf("%d",C[i]); return 0; }
The mul function can be simplified as follows:
vector<int> mul(vector<int> &A,int b) { vector<int> C; if (b==0){ //Similarly, 0 data needs special judgment C.push_back(0); return C; } int t =0; for (int i =0;i<A.size()||t;i++){ //Add a "||t" condition judgment, either i does not complete the cycle, or T is not 0 if (i<A.size()) t+=A[i]*b; //Because conditions are added above, the following multiple judgments determine whether i is within the range of A C.push_back(t%10); //Single digits of t t=t/10; //Carry of t } return C; }
High precision except low precision
Train of thought:
138/12
Starting from the highest bit, 1 / 12 = 0... 1, 1 falls to the next bit
The remainder of the above formula * 10 + the second digit: (1 * 10 + 3) / 12 = 1... 1, 1 to the next digit
Similarly: (1 * 10 + 8) / 12 = 1... 6
Get the answer 011, remove the highest bit 0, and the answer is 11... 6
Division returns the remainder in addition to the quotient:
The code implementation is as follows:
#include <iostream> //< vector > comes with a size function to find the length #include <vector> #Include < algorithm > / / this header file contains the function reverse using namespace std; //Array length + 10 prevents boundary problems const int N=1e6+10; //Write a method that returns the vector type //The address character is taken here because the reference type is faster vector<int> div(vector<int> &A,int b,int &r)//r is the remainder. The address character is used to directly change the value of r { vector<int> C; r=0; for(int i=A.size()-1;i>=0;i--){ //Division needs to start with the high-order number, so for is a positive loop r=r*10+A[i]; C.push_back(r/b); r=(r%b); } reverse(C.begin(),C.end()); //Because the final result of C is in positive order and the output of C is in reverse order, it should be reversed while (C.size()>1&& C.back()==0) C.pop_back(); //Remove the leading 0 sentence and put it after reverse! return C; } int main(){ //a the number is too long, read it with string, b can read it directly string a; int b,r; //Save a to vector vector<int> A; cin>>a>>b; //Deposit from low position for(int i=a.size()-1;i>=0;i--) A.push_back(a[i]-'0'); auto C = div(A,b,r); //Output from the end of the vector for(int i =C.size()-1;i>=0;i--) printf("%d",C[i]); cout<<endl<<r<<endl; return 0; }
In fact, the input and output parts of high-precision calculation are not much different, mainly in the function template
In particular, high-precision division requires setting the remainder in the function.