Premier Bob的算法模板库

前言

我是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’!”(都是套路(模板))

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值