前言
我是Premier Bob,这是我的在线算法模板库。热烈欢迎NEYC和NEYCBS的同学们来此参观。
强烈建议同学们在我的博客目录中找到各模板的链接!
我的博客目录:Premier Bob的博客文章目录
废了九牛二虎之力写了几个自己的模板,都写成了“.hpp”的格式(其实并没有必要),而且大量使用“namespace”。以下是这些文件的代码,代码风格看起来倒像是工程。虽然变量、函数名十分“啰嗦”,但是却很容易看出它们的意义。模板直接插入代码时,请删去第二行“#pragma once”。(另外,请忽略模板中的换行问题,因为有的行实在是太长了!)
这些模板应该都很靠谱,我都一一测试过,如果代码有问题可以联系我。
此页面仍在完善,博文可能经常撤回修改,审核时无法进入属正常现象。
Euler_Prime .hpp (欧拉线筛求素数)
//made by GGN -from NEYC
#pragma once
//pulic functions:
//SolvePrime(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 Solved=0;
//store of SolvePrime functions
int MaxSolveNum=0;
//the biggist number you have solved
void AddPrime(int PrimeNow)
{
PrimeTable[++PrimeCount]=PrimeNow;
}
void SolvePrime(int NumMaxNow)
{
//NumMax section check
if(NumMaxNow<=1)
{
printf("Error in \"Euler_Prime\":SolvePrime NumMaxNow= %d (<=1) is not allowed!\n",NumMaxNow);
system("pause>nul");
return;
}
if(NumMaxNow>=NumMax)
{
printf("Error in \"Euler_Prime\":SolvePrime NumMaxNow= %d is greater than NumMax= %d!\n",NumMaxNow,NumMax);
system("pause>nul");
return;
}
//Store MaxSolveNum
MaxSolveNum=NumMaxNow;
Solved=1;
NotPrime[0]=NotPrime[1]=1;
for(int i=2;i<=NumMaxNow;i++)
{
if(!NotPrime[i])
AddPrime(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 solved
if(Solved==0)
{
printf("Error in \"Euler_Prime\":PrimeCheck PrimeTable has not been solved!\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>MaxSolveNum)
{
printf("Error in \"Euler_Prime\":PrimeCheck x= %d is greater than MaxSolveNum= %d!\n",x,MaxSolveNum);
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 HasSolved=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)
{
HasSolved=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()
{
//solved check
if(!HasSolved)
{
printf("Error in \"KMP\":AppearTimeCount you have not solved KMP yet!\n");
system("pause>nul");
return 0;
}
return Position.size();
}
int AppearPosition(int AppearTime)
{
//solved check
if(!HasSolved)
{
printf("Elror in \"KMP\":AppearPosition you have not solved 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 solve 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)
{
printf("Error \"Trie\":InsertString Value=0 (0 means not found) is not allowed!\n");
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;
}
Radix_Counting_Sort .hpp (线性时间复杂度排序)
//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;
}
}
}
namespace Radix_Sort
{
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;}
void RadixSort(int* Array,int SizeOfArray)
{
//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;
#include"Radix_Counting_Sort.hpp"
int main()
{
int a[14]={0,123,12,321,213,5,678,4,2,14,99};
Radix_Sort::RadixSort(a,10);
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 (快速傅里叶变换大整数乘法)
改编自Leo的FFT博客。
#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');
}
后记
模板库仍在扩充,欢迎各路豪杰出谋划策。
算法学无止境,模板亦是无穷。仍凭风吹雨打,我自专心写代码。
最后引用goseqh学长的一句话:“Full of ‘Template’!”(都是套路(模板))