# Premier Bob的算法模板库

## Euler_Prime .hpp （欧拉线筛求素数）

//made by GGN -from NEYC
#pragma once

//pulic functions:
//SovePrime(int NumMaxNow)
//PrimeCheck(int x)
//PrimeList(int Index)

#include<cstdio>
#include<cstdlib>

namespace Euler_Prime
{
const int NumMax=100000001;
const int PrimeCountMax=5761456;
//you can use this to change the size of Array

int PrimeTable[PrimeCountMax]={};
int PrimeCount=0;
bool NotPrime[NumMax]={};
bool Soved=0;
//store of SovePrime functions

int MaxSoveNum=0;
//the biggist number you have soved

{
PrimeTable[++PrimeCount]=PrimeNow;
}

void SovePrime(int NumMaxNow)
{
//NumMax section check
if(NumMaxNow<=1)
{
printf("Error in \"Euler_Prime\":SovePrime NumMaxNow= %d (<=1) is not allowed!\n",NumMaxNow);
system("pause>nul");
return;
}
if(NumMaxNow>=NumMax)
{
printf("Error in \"Euler_Prime\":SovePrime NumMaxNow= %d is greater than NumMax= %d!\n",NumMaxNow,NumMax);
system("pause>nul");
return;
}

//Store MaxSoveNum
MaxSoveNum=NumMaxNow;
Soved=1;

NotPrime[0]=NotPrime[1]=1;
for(int i=2;i<=NumMaxNow;i++)
{
if(!NotPrime[i])
for(int j=1;j<=PrimeCount && i*PrimeTable[j]<=NumMaxNow;j++)
{
NotPrime[i*PrimeTable[j]]=1;
if(i%PrimeTable[j]==0)
break;
}
}
}

bool PrimeCheck(int x)
{
//check soved
if(Soved==0)
{
printf("Error in \"Euler_Prime\":PrimeCheck PrimeTable has not been soved!\n");
system("pause>nul");
return 0;
}

//check section of x
if(x<0)
{
printf("Error in \"Euler_Prime\":PrimeCheck x= %d (<0) is not allowed!\n",x);
system("pause>nul");
return 0;
}
if(x>MaxSoveNum)
{
printf("Error in \"Euler_Prime\":PrimeCheck x= %d is greater than MaxSoveNum= %d!\n",x,MaxSoveNum);
system("pause>nul");
return 0;
}

return !NotPrime[x];
}

int PrimeList(int Index)
{
//check section of Index
if(Index<=0)
{
printf("Error in \"Euler_Prime\":PrimeList Index= %d (<=0) is not allowed!\n",Index);
system("pause>nul");
return 0;
}
if(Index>=PrimeCountMax)
{
printf("Error in \"Euler_Prime\":PrimeList Index= %d is greater than PrimeCountMax= %d!\n",Index,PrimeCountMax);
system("pause>nul");
return 0;
}
return PrimeTable[Index];
}
}

## KMP .hpp （KMP单模式串匹配）

//made by GGN -from NEYC
#pragma once

//pubilc functions:
//strlen(const char*String)
//GetFail(const char* PatternString)
//KMP(const char* TextString,const char* PatternString)
//AppearTimeCount()
//AppearPostion(int AppearTime)

#include<cstdio>
#include<cstdlib>
#include<vector>
using namespace std;

namespace KMP
{
const int PatternLengthMax=1048576;
//you can use this to change the length of array
vector<int>Position;

int FailPointer[PatternLengthMax]={};
//FailPointer

bool HasSoved=0;

int strlen(const char* String)
{
//we use this to calculate the length of a string
int i;
for(i=0;String[i]!=0;i++);
return i;
}

void GetFail(const char* PatternString)
{
//this function is used to init Failpointer
int PLength=strlen(PatternString);

//Length check
if(PLength==0)
{
printf("Error in \"KMP\":GetFail PatternString\'s length=0 is not allowed!\n");
system("pause>nul");
return;
}

FailPointer[0]=FailPointer[1]=0;
for(int i=1;i<=PLength;i++)
{
int j=FailPointer[i];
while(j!=0 && PatternString[i]!=PatternString[j])
j=FailPointer[j];
FailPointer[i+1]= PatternString[i]==PatternString[j] ? j+1 : 0;
}
}

void KMP(const char* TextString,const char* PatternString)
{
HasSoved=1;
Position.clear();
int TLength=strlen(TextString),PLength=strlen(PatternString);

//init GetFail
GetFail(PatternString);

//length check
if(PLength>TLength)
{
printf("Error in \"KMP\":KMP PatternString is longer than TextString!\n");
system("pause>nul");
return;
}

int j=0;
for(int i=0;i<TLength;i++)
{
while(j!=0 && TextString[i]!=PatternString[j])
j=FailPointer[j];
if(TextString[i]==PatternString[j])
j++;
if(j==PLength)
Position.push_back(i-PLength+1);
}
}

int AppearTimeCount()
{
//soved check
if(!HasSoved)
{
printf("Error in \"KMP\":AppearTimeCount you have not soved KMP yet!\n");
system("pause>nul");
return 0;
}
return Position.size();
}

int AppearPosition(int AppearTime)
{
//soved check
if(!HasSoved)
{
printf("Error in \"KMP\":AppearPosition you have not soved KMP yet!\n");
system("pause>nul");
return 0;
}

if(1<=AppearTime && AppearTime<=Position.size())
return Position[AppearTime-1];
else{
printf("Error in \"KMP\":AppearPosition AppearTime= %d is not allowed!\n");
system("pause>nul");
}
return 0;
}
}

## Sparse_Table .hpp （静态区间最小值）

//made by GGN -from NEYC
#pragma once

//pulic functions:
//Init(int* Array,int ArrayLength)
//RMQ(int Left,int Right)

#include<cstdio>
#include<cstdlib>

namespace Sparse_Table
{
//this is the namespace for "Sparse-Table" algorithm

const int MaxLength=32768;
const int LgMaxLength=16;
bool HasInit=0;
int ArrayLenNow=0;
//you can use this to change the max length of queue

int d[MaxLength][LgMaxLength]={};
//this is the main table to store out information
//d[i][j] means: RMQ of queue [i,i+(2^j)-1]

int min(int a,int b)
{
//find the smaller one between two integers
return a<b ? a : b;
}

void Init(int* Array,int ArrayLength)
{
//you must Init the Table befor you use it
HasInit=1;
ArrayLenNow=ArrayLength;

//!!attention:
//we use the section [1,ArrayLength] in the Queue
//but not [0,ArrayLength-1]

for(int i=1;i<=ArrayLength;i++)
d[i][0]=Array[i];
for(int j=1;(1<<j)<=ArrayLength;j++)
for(int i=1;i+(1<<j)-1<=ArrayLength;i++)
d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}

int RMQ(int L,int R)
{
//we use this function to sove RMQ

//Init check
if(HasInit==0)
{
printf("Error in \"Sparse-Table\":You have to \"Init\" before you use the Sparse-Table!\n");
system("pause>nul");
return -1;
}

//Section check
if(!(1<=L && L<=R && R<=ArrayLenNow))
{
printf("Error in \"Sparse-Table\":Query asked [%d,%d] is not in full section [%d,%d]!\n",L,R,1,ArrayLenNow);
system("pause>nul");
return -1;
}

//to find the RMQ of queue [L,R]

int j=0;
while((1<<(j+1))<R-L+1)
j++;
return min(d[L][j],d[R-(1<<j)+1][j]);
}
}

## Trie .hpp （字典树）

//made by GGN -NEYC
#pragma once

#include<cstdio>
#include<cstdlib>

namespace Trie
{
const int NormalCharCount=26,ASCII_CharCount=128,AllCharCount=256;

const int AllChar=26;
const int NodeMax=1048576;
//We use this to control child node count
//AllChar=26_Normal 128_ASCII 256_AllChar

int NormalIndex(char CharInput){return CharInput-'a';}
//only can be used to index small letter

int ASCII_Index(char CharInput){return CharInput;}
//used when char=0~127

int AllCharIndex(char CharInput){return CharInput+128;}
//used for all char

int FreeIndex(char CharInput)
{
switch(AllChar)
{
case NormalCharCount:
return NormalIndex(CharInput);
case ASCII_CharCount:
return ASCII_Index(CharInput);
case AllCharCount:
return AllCharIndex(CharInput);
}
printf("Error \"Trie\":FreeIndex AllChar= %d is not allowed!(not 26,128,256)\n",AllChar);
system("pause>nul");
return -1;
}

struct TrieNode{int Next[AllChar];int Value;TrieNode(){Value=0;}};
//you can also add sth else to the structure

class Trie
{
TrieNode Nodes[NodeMax];
//define trieNodes

int NodeTop;
//To Use the nodes

int NewNode(){return NodeTop++;}
//top a new node
public:

Trie()
{
NodeTop=1;
}

int InsertString(const char* StrToInsert,int StringValue)
{
int NodeNow=0;
for(int i=0;StrToInsert[i]!=0;i++)
{
int CharNow=FreeIndex(StrToInsert[i]);
if(!(0<=CharNow && CharNow<NodeMax))
{
printf("Error \"Trie\":InsertString String's charType not agree to AllChar=%d!\n",AllChar);
switch(AllChar)
{
case NormalCharCount:
printf("this means you can only use [small letter] in your insert string!\n");
break;
case ASCII_CharCount:
printf("this means you can only use the char whose ASCII code is [above zero]!\n");
break;
case AllCharCount:
printf("this means you can add [all type of char] to the Trie!\n");
break;
default:
printf("Your AllChar= %d,which is not allowed (it can only be 26,128 or 256)!\n",AllChar);
}
printf("and your Error char is \"%c\"!\n",StrToInsert[i]);
system("pause>nul");
return -1;
}
if(Nodes[NodeNow].Next[CharNow]==0)
{
if(NodeTop==NodeMax)
{
printf("Error \"Trie\":InsertString NodeStack Full NodeTop=MaxNode= %d!\n",NodeTop);
system("pause>nul");
return -1;
}
Nodes[NodeNow].Next[CharNow]=NewNode();
}
NodeNow=Nodes[NodeNow].Next[CharNow];
}

//check value
if(StringValue==0)
{
system("pause>nul");
return -1;
}
Nodes[NodeNow].Value=StringValue;
return StringValue;
}

//search a string's value in the Trie
int SearchString(const char* StrToSearch)
{
int NodeNow=0;
for(int i=0;StrToSearch[i]!=0;i++)
{
int CharNow=FreeIndex(StrToSearch[i]);
if(Nodes[NodeNow].Next[CharNow]==0)
return 0;
NodeNow=Nodes[NodeNow].Next[CharNow];
}
return Nodes[NodeNow].Value;
}
};
}

#include"Trie.hpp"
Trie::Trie NTR;
int main()
{
NTR.InsertString("abcd",1234567);
printf("%d\n",NTR.SearchString("abcd"));
system("pause");
return 0;
}


//made by GGN -NEYC
#pragma once

//you can use this header to sort in a short time

#include<cstring>
#include<cstdio>
#include<cstdlib>

namespace Counting_Sort
{
const int MinNumber=0;
const int MaxNumber=1048576;
//you can use this to change the size of arrays
//numbers must between MinNumber~MaxNumber

const int MaxStore=MaxNumber-MinNumber+1;
int NumberCount[MaxStore];
bool Used=0;
//you can use the NumberCount without Init for the first time
//but you must init it before you use it a second time

int IndexNumber(int NumberNow){return NumberNow-MinNumber;}

int ReIndexNumber(int IndexNumber){return IndexNumber+MinNumber;}

int min(int a,int b){return a<b ? a : b;}

int max(int a,int b){return a>b ? a : b;}

void CountingSort(int* Array,int SizeOfArray)
{
//the main function to sort an array

//!attention:we sort the section of Array[1 to SizeOfArray]
//but not [0 to SizeOfArray-1]

//check init
if(Used==1)
memset(NumberCount,0,sizeof(NumberCount));
else
Used=1;

//find the max and  min index
int MinIndexNow,MaxIndexNow;

//store the message
for(int i=1;i<=SizeOfArray;i++)
{
int IndexNumberNow=IndexNumber(Array[i]);
if(IndexNumberNow<0 || IndexNumberNow>=MaxStore)
{
printf("Error \"Counting_Sort\":CountingSort Array[%d]=%d is not allowed (NumberSection is [%d,%d])!\n",i,Array[i],MinNumber,MaxNumber);
system("pause>nul");
return;
}
if(i==1)
{
MinIndexNow=MaxIndexNow=IndexNumberNow;
}else{
MinIndexNow=min(MinIndexNow,IndexNumberNow);
MaxIndexNow=max(MaxIndexNow,IndexNumberNow);
}
NumberCount[IndexNumberNow]++;
}

//push the numbers back to array
int ArrayPosition=1;
for(int i=MinIndexNow;i<=MaxIndexNow;i++)
{
int NumberNow=ReIndexNumber(i);
for(int k=1;k<=NumberCount[i];k++)
Array[ArrayPosition++]=NumberNow;
}
}

}

{
const int MaxSizeOfArray=1048576;
//you can use this to change the size of string

int NumberCount[10][MaxSizeOfArray];
int BitNumCount[10];
bool Used=0;

long long TenPow[11]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000};

int GetBit(int NumberNow,int BitNow){return (NumberNow/TenPow[BitNow-1])%10;}
int RightMove(int NumberNow,int BitNow){return NumberNow/TenPow[BitNow-1];}

void PushNumber(int NumberToPush,int BitNum){NumberCount[BitNum][++BitNumCount[BitNum]]=NumberToPush;}

int max(int a,int b){return a>b ? a : b;}

{
//find max num
int MaxNumber=Array[1];
for(int i=2;i<=SizeOfArray;i++)
MaxNumber=max(MaxNumber,Array[i]);

//Store numbers
for(int j=1;RightMove(MaxNumber,j)!=0;j++)
{
//check init
if(Used==1)
{
memset(NumberCount,0,sizeof(NumberCount));
memset(BitNumCount,0,sizeof(BitNumCount));
}else
Used=1;

//push number
for(int i=1;i<=SizeOfArray;i++)
{
int BitNow=GetBit(Array[i],j);
PushNumber(Array[i],BitNow);
}
int PositionNow=1;
for(int i=0;i<10;i++)
for(int k=1;k<=BitNumCount[i];k++)
Array[PositionNow++]=NumberCount[i][k];
}
}
}


#include<iostream>
using namespace std;
int main()
{
int a[14]={0,123,12,321,213,5,678,4,2,14,99};
for(int i=1;i<=10;i++)
cout<<a[i]<<" ";
cout<<endl;
system("pause");
return 0;
}

## BigNum .hpp （大整数运算（朴素））

//made by Premier Bob -from NEYC
#pragma once

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cstring>
using namespace std;

namespace BigNum
{
struct BigNum
{
//the structure for BigNum
int a[1001];
int Length;

void StoreNum(int NumToStore)
{
//Store a int number
Length=0;
memset(a,0,sizeof(a));
if(NumToStore<0)
{
printf("Error \"BigNum\":BigNum::StoreNum X=%d (<0) is not allowed!\n",NumToStore);
system("pause>nul");
return;
}
while(NumToStore!=0)
{
a[++Length]=NumToStore%10;
NumToStore/=10;
}
}

void StoreNum(long long NumToStore)
{
//Store a long long number
Length=0;
memset(a,0,sizeof(a));
if(NumToStore<0)
{
printf("Error \"BigNum\":BigNum::StoreNum X=%d (<0) is not allowed!\n",NumToStore);
system("pause>nul");
return;
}
while(NumToStore!=0)
{
a[++Length]=NumToStore%10;
NumToStore/=10;
}
}

void StoreNum(const char* StrToStore)
{
//store a string number
int StringLength=strlen(StrToStore);
Length=StringLength;
memset(a,0,sizeof(a));
for(int i=StringLength-1;i>=0;i--)
{
if(StrToStore[i]<'0' || StrToStore[i]>'9')
{
printf("Error \"BigNum\":BigNum::StoreNum StrToStore[%d]=%d (<\'0\' or > \'9\') which is not allowed!\n",i,(int)StrToStore[i]);
if(32<=StrToStore[i] && StrToStore[i]<127)
printf("the Error Char is\"%c\"!\n",StrToStore[i]);
system("pause>nul");
return;
}
a[StringLength-i]=StrToStore[i]-'0';
}
}
BigNum(){Length=0;}
BigNum(int x){StoreNum(x);}
BigNum(long long x){StoreNum(x);}
BigNum(const char* x){StoreNum(x);}

int IntForm()
{
if(Length>=10)
{
printf("Error \"BigNum\":BigNum::IntForm the Number is too large,Length=%d (>=10)");
system("pause>nul");
return -1;
}
int x=0;
for(int i=1;i<=Length;i++)
{
x*=10;
x+=a[i];
}
return x;
}

long long LongForm()
{
if(Length>=19)
{
printf("Error \"BigNum\":BigNum::LongForm the Number is too large,Length=%d (>=19)");
system("pause>nul");
return -1;
}
long long x=0;
for(int i=1;i<=Length;i++)
{
x*=10;
x+=a[i];
}
return x;
}
};

ostream& operator<<(ostream& out,BigNum NumToOutput)
{
if(NumToOutput.Length==0)
{
out<<"0";
return out;
}
for(int i=NumToOutput.Length;i>0;i--)
out<<NumToOutput.a[i];
return out;
}

istream& operator>>(istream& in,BigNum& NumNeedIn)
{
char StrToPush[1001]={};
cin>>StrToPush;
NumNeedIn=BigNum(StrToPush);
return in;
}

BigNum operator+(BigNum x,BigNum y)
{
BigNum ans(0);
ans.Length=max(x.Length,y.Length)+1;
for(int i=1;i<=ans.Length;i++)
{
ans.a[i]+=x.a[i]+y.a[i];
ans.a[i+1]+=ans.a[i]/10;
ans.a[i]%=10;
}
if(ans.a[ans.Length]==0)
ans.Length--;
return ans;
}

BigNum operator*(BigNum x,BigNum y)
{
BigNum ans(0);
ans.Length=x.Length+y.Length;
for(int i=1;i<=x.Length;i++)
for(int j=1;j<=y.Length;j++)
{
ans.a[i+j-1]+=x.a[i]*y.a[j];
ans.a[i+j]+=ans.a[i+j-1]/10;
ans.a[i+j-1]%=10;
}
if(ans.a[ans.Length]==0)
ans.Length--;
return ans;
}

bool  operator<(BigNum x,BigNum y)
{
if(x.Length>y.Length)
return 0;
if(x.Length<y.Length)
return 1;
for(int i=x.Length;i>=1;i--)
if(x.a[i]<y.a[i])
return 1;
else if(x.a[i]>y.a[i])
return 0;
return 0;
}

bool operator>(BigNum x,BigNum y){return (y<x);}

bool operator==(BigNum x,BigNum y)
{
if(x.Length!=y.Length)
return 0;
for(int i=x.Length;i>=1;i--)
if(x.a[i]!=y.a[i])
return 0;
return 1;
}

BigNum operator-(BigNum x,BigNum y)
{
BigNum ans(0);
if(x<y)
{
printf("Error \"BigNum\":operator\"-\" in \"x-y\" x<y which is not allowed!\n");
printf("x=");cout<<x<<endl;
printf("y=");cout<<y<<endl;
system("pause>nul");
return ans;
}
ans=x;
for(int i=1;i<=x.Length;i++)
{
ans.a[i]-=y.a[i];
if(ans.a[i]<0)
{
ans.a[i+1]--;
ans.a[i]+=10;
}
}
while(ans.a[ans.Length]==0)
ans.Length--;
return ans;
}

BigNum operator/(BigNum x,long long y)
{
BigNum ans(0);
long long modCount=0;
if(y<=0)
{
printf("Error \"BigNum\":operator\"/\" y=%d (<=0) is not allowed!\n",y);
system("pause>nul");
return ans;
}
ans.Length=x.Length;
for(int i=1;i<=x.Length;i++)
{
ans.a[i]=(modCount*10+x.a[i])/y;
modCount=(modCount*10+x.a[i])%y;
}
while(ans.a[ans.Length]==0)
ans.Length--;
return ans;
}

BigNum operator/(BigNum x,int y)
{
BigNum ans(0);
int modCount=0;
if(y<=0)
{
printf("Error \"BigNum\":operator\"/\" y=%d (<=0) is not allowed!\n",y);
system("pause>nul");
return ans;
}
ans.Length=x.Length;
for(int i=x.Length;i>=1;i--)
{
ans.a[i]=(modCount*10+x.a[i])/y;
modCount=(modCount*10+x.a[i])%y;
}
while(ans.a[ans.Length]==0)
ans.Length--;
return ans;
}

BigNum operator+(BigNum x,int y){return x+BigNum(y);}
BigNum operator+(BigNum x,long long y){return x+BigNum(y);}
BigNum operator+(BigNum x,const char* y){return x+BigNum(y);}

BigNum operator-(BigNum x,int y){return x-BigNum(y);}
BigNum operator-(BigNum x,long long y){return x-BigNum(y);}
BigNum operator-(BigNum x,const char* y){return x-BigNum(y);}

BigNum operator*(BigNum x,int y){return x*BigNum(y);}
BigNum operator*(BigNum x,long long y){return x*BigNum(y);}
BigNum operator*(BigNum x,const char* y){return x*BigNum(y);}

int operator%(BigNum x,int y)
{
int modCount=0;
if(y<=0)
{
printf("Error \"BigNum\":operator\"%\" y=%d (<=0) is not allowed!\n",y);
system("pause>nul");
return -1;
}
for(int i=x.Length;i>=1;i--)
modCount=(modCount*10+x.a[i])%y;
return modCount;
}

long long operator%(BigNum x,long long y)
{
long long modCount=0;
if(y<=0)
{
printf("Error \"BigNum\":operator\"%\" y=%d (<=0) is not allowed!\n",y);
system("pause>nul");
return -1;
}
for(int i=x.Length;i>=1;i--)
modCount=(modCount*10+x.a[i])%y;
return modCount;
}
}

#include<iostream>
using namespace std;
#include"BigNum.hpp"
int main()
{
BigNum::BigNum x;int y;
cout<<"x=";cin>>x;
cout<<"y=";cin>>y;
cout<<"----------"<<endl;
cout<<"x+y="<<x+y<<endl;
cout<<"x-y="<<x-y<<endl;
cout<<"x*y="<<x*y<<endl;
cout<<"x/y="<<x/y<<endl;
cout<<"x%y="<<x%y<<endl;
system("pause");
return 0;
}

## FFT_Multiply .hpp （快速傅里叶变换大整数乘法）

#include<algorithm>
#include<cstring>
#include<complex>
using namespace std;

namespace FFT_Multiply
{
const int MaxLength=2097153;
const double PI=acos(-1.0);

int LengthOfStr1,LengthOfStr2;
int FFT_Length;
int FinalNum[MaxLength];

typedef complex<double> ComplexDouble;

ComplexDouble NumA[MaxLength];
ComplexDouble NumB[MaxLength];
char NumAns[MaxLength];

const int DFT_MODE=1,IDFT_MODE=-1;

int Reversal[MaxLength];
void GetReversal(int BitCount)
{
for(int i=0;i<(1<<BitCount);i++)
Reversal[i]=(Reversal[i>>1]>>1)|((i&1)<<(BitCount-1));
}

void FFT(ComplexDouble *ArguArray,int Length,int FFT_Method)
{
for(int i=0;i<Length;i++)
if(i<Reversal[i])
swap(ArguArray[i],ArguArray[Reversal[i]]);
for(int Step=1;Step<Length;Step<<=1)
{
ComplexDouble OmegaN=exp(ComplexDouble(0,FFT_Method*PI/Step));
for(int j=0;j<Length;j+=Step<<1)
{
ComplexDouble OmegaN_K(1,0);
for(int k=j;k<j+Step;k++)
{
ComplexDouble X=ArguArray[k];
ComplexDouble Y=OmegaN_K*ArguArray[k+Step];
ArguArray[k]=X+Y;
ArguArray[k+Step]=X-Y;
OmegaN_K*=OmegaN;
}
}
}
if(FFT_Method==IDFT_MODE)
for(int i=0;i<Length;i++)
ArguArray[i]/=Length;
}

void LoadNum(const char* Num1,const char* Num2)
{
LengthOfStr1=strlen(Num1);
LengthOfStr2=strlen(Num2);
FFT_Length=2;
int BitMax=1;
for(BitMax=1;(1<<BitMax)<LengthOfStr1+LengthOfStr2-1;BitMax++)
FFT_Length<<=1;
for(int i=0;i<LengthOfStr1;i++)
NumA[i]=(double)(Num1[LengthOfStr1-i-1]-'0');
for(int i=0;i<LengthOfStr2;i++)
NumB[i]=(double)(Num2[LengthOfStr2-i-1]-'0');
GetReversal(BitMax);
}

void Multiply()
{
FFT(NumA,FFT_Length,DFT_MODE);
FFT(NumB,FFT_Length,DFT_MODE);
for(int i=0;i<FFT_Length;i++)
NumA[i]*=NumB[i];
FFT(NumA,FFT_Length,-1);
for(int i=0;i<FFT_Length;i++)
{
FinalNum[i]+=(int)(NumA[i].real()+0.5);
FinalNum[i+1]+=FinalNum[i]/10;
FinalNum[i]%=10;
}
}

int FinalLength;
void GetFinalLength(){for(FinalLength=LengthOfStr1+LengthOfStr2;!FinalNum[FinalLength]&&FinalLength>=0;FinalLength--);}

void OutputString()
{
if(FinalLength==-1)
printf("0");
for(int i=FinalLength;i>=0;i--)
printf("%d",FinalNum[i]);
}

void OutputString(char* NumTo)
{
if(FinalLength==-1)
sprintf(NumTo,"0");
int PosNow=0;
for(int i=FinalLength;i>=0;i--,PosNow++)
sprintf(&NumTo[PosNow],"%d",FinalNum[i]);
}

void Multiply(const char* Num1,const char* Num2){LoadNum(Num1,Num2);Multiply();GetFinalLength();OutputString(NumAns);}
}

#include"FFT_Multiply.hpp"
char s1[2097153],s2[2097153];
int main()
{
scanf("%s%s",s1,s2);
FFT_Multiply::Multiply(s1,s2);
printf("%s",FFT_Multiply::NumAns);
putchar('\n');
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120