Premier Bob的算法模板库

前言

我是Premier Bob,这是我的在线算法模板库。热烈欢迎NEYC和NEYCBS的同学们来此参观。

强烈建议同学们在我的博客目录中找到各模板的链接!

我的博客目录:Premier Bob的博客文章目录

废了九牛二虎之力写了几个自己的模板,都写成了“.hpp”的格式(其实并没有必要),而且大量使用“namespace”。以下是这些文件的代码,代码风格看起来倒像是工程。虽然变量、函数名十分“啰嗦”,但是却很容易看出它们的意义。模板直接插入代码时,请删去第二行“#pragma once”。(另外,请忽略模板中的换行问题,因为有的行实在是太长了!)

这些模板应该都很靠谱,我都一一测试过,如果代码有问题可以联系我。

此页面仍在完善,博文可能经常撤回修改,审核时无法进入属正常现象。


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

    void AddPrime(int PrimeNow)
    {
        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])
                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 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)
            {
                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’!”(都是套路(模板))

猜你喜欢

转载自blog.csdn.net/ggn_2015/article/details/69660610