zoukankan      html  css  js  c++  java
  • [原创]数论个人模板

          作为一个ACMer不可能没有自己的模板,并不是别人的模板你都能看的懂,所以有自己的模板很重要,下面是我自己一边培训一边整的数论模板,内容很少都是一些数论基础模板(毕竟不是大牛),但是此博客会一直更新的,有新内容我会马上添加进来的,如果有错误,请指出,谢谢。

    1数论基础

    1)、数学公式

    1^3+2^3+3^3+……+n^3=[n(n+1)/2]^2 

    斐波那契数列通项公式为:

         f(n)=1/sqrt(5)(((1+sqrt(5))/2)^n+((1-sqrt(5))/2)^n)

    若取前面k位的话:

         ans= -0.5*(log10(5.0))+m*log10((sqrt(5.0)+1.0)/2));

    ans -= (int)ans; ans=pow(10.0,ans);ans *= 10^(k-1);取整

    对于a^b取前几位:

    LL Pow2(LL a , LL b) {

        double s = log10(double(a)) * b - LL(log10(double(a)) * b);

        s = pow(10,s);

        return s * 100;//这里是取a^b前三位

    }

    给一串不定长数字、空格字符,获取里面的数字。

    C++

    #include<sstream>

    string s;

    while (getchar() != ' ');

    getline(cin,s);

    int index = 0;

    stringstream ss(s);

    while (ss >> a[index])  ++index;

    C

    while (getchar() != ' ');

    while ((buf = getchar()) != ' ')  

    if (buf >= '0' && buf <= '9') {  

        ungetc(buf,stdin);  

         scanf("%d",&data[count ++]);  

    2)、九余数定理

         给一个数取每一位上的数字相加直到相加等于小于10的数,678=6+7+8=21=2+1=3

         ans  =  n%9 ; if(ans==0 )ans=9;   

    3) 、辗转相除法求最大公约数

    int gcd(int x, int y){          return (!y)?x:gcd(y, x%y);     }

    4)、威尔逊定理

    ,其中p为素数。

    5)、裴蜀定理(或贝祖定理

    abgcd(a,b) = d; 一定存在 ax+by = d;

    6)、扩展欧几里得算法(求逆元)

       http://blog.csdn.net/zhjchengfeng5/article/details/7786595

       ax≡c(mod b).  等价于 ax+by=c,求最小x

       通解方程:

        x =x0 + (b/gcd)*t(t为>=0的整数)

         y = y0 -(a/gcd)*t (t为>=0的整数)

    LL e_gcd(LL a,LL b,LL &x,LL &y){

        LL d=a;

        if(b==0){

            x=1;y=0;

        }

        else{

            d=e_gcd(b,a%b,y,x);

            y-=(a/b)*x;

        }

        return d;

    }

    LL cal(LL a,LL b,LL c){

        LL x,y;

        LL gcd=e_gcd(a,b,x,y);

        if(c%gcd!=0) return -1;

        LL t=b/gcd;

        return (x* c / gcd % t + t) % t;

    }

    7)、中国剩余定理(同余式)

    a .、数组元素互质的情况

    xa1(mod m1)

    xa2(mod m2)…..

    int Chinese_Remainder(int a[],int m[],int len)  // a[]存放余数  m[]存放两两互质的数

    {

    int i,d,x,y,Mi;

    int ret=0;

    int M=1;

    for (i=0;i<len;i++) M*=m[i];//M是所有质数的乘积

    for (i=0;i<len;i++)

    {

    Mi=M/m[i];//Mi是除m[i]外的所有质数的乘积

    d= e_gcd (Mi,m[i],x,y);//Mi*x1(mod m[i])->xMim[i]的数论倒数

    ret=(ret+x*Mi*a[i])%M;//X= ∑ a[i]*x*Mi

    }

    return (M+ret%M)%M;

    }

    m数组元素不一定互质的情况

    LL Chinese_Remainder (LL n,LL m[],LL a[]){

        LL m1,r1,m2,r2,flag=0,i,d,x,y,c,t;

        m1=m[0],r1=a[0];

        flag=0;

        for(i=1;i<n;i++) {

            m2=m[i],r2=a[i];

            if(flag)continue;

            d = e_gcd (m1,m2,x,y);

            c=r2-r1;

            if(c%d) {//对于方程m1*x+m2*y=c,如果c不是d的倍数就无整数解

                flag=1;

                continue;

            }

            t=m2/d;//对于方程m1x+m2y=c=r2-r1,(x0,y0)是一组整数解,那么(x0+k*m2/d,y0-k*m1/d)也是一组整数解(k为任意整数)

            x=(c/d*x%t+t)%t;// x0=x*c/d,y0=x*c/d;保证x0是正数

            r1=m1*x+r1;//新求的r1就是前i组的解,Mi=m1*x+M(i-1)=r2-m2*y(m1为前im的最小公倍数);m2取余时,余数为r2//对以前的m取余时,Mi%m=m1*x%m+M(i-1)%m=M(i-1)%m=r

            m1=m1*m2/d;//m1为新的最小公倍数

        }

        if(flag)return -1;

        if(n==1&&r1==0)return m1;//结果不能为0

        return r1;

    }

    8)、筛法求素数、求因子个数

    、运用筛法打印素数表

    int prime[N]={0};

    int flag[N]={0};

    int Count[N]={0};

    void PrimeTable(){

        int index=0;

        for(int i=2;i<=N;i++){

            if(!flag[i]){

                prime[index++]=i;

                for(int j=i*i; j<=N; j+=i) {

                    flag[j]=1;

                }

            }

        }

    }

    、求X的因子个数,通过刚刚的素数表来计算

    void Count_factor(int x){

        int i=0;

        int xx=x;

        Count[xx]=1;

        while(x>=prime[i]){

            int cc=0;

            while(x%prime[i]==0){

                x/=prime[i];

                cc++;

            }

            i++;

            Count[xx]=Count[xx]*(cc+1);

        }

    }

    c、求X因子的和(不加本身打表)

    void init(){

        Count[0] = Count[1] = 0;

        for(int i = 2;i < N;i++){

            Count[i] = 1;

        }

        for(int i = 2;i <= N/2; i++){

            for(int j = i+i;j < N;j += i) {

                Count[j] += i;

            }

        }

    }

    9)、费马小定理(快速幂取模)

    __int64 qpow(__int64 a,__int64 b,__int64 m){

        __int64 ans=1;

        while (b>0){

            if (b&1)  ans=(ans*a)%m;

            b >>= 1;

            a=(a*a)%m;

        }

        return ans;

    }

    10) 、矩阵快速幂

    int n,m;//n矩阵大小,m矩阵个数

    struct matrix{

        int a[1][1];

    } origin,res;

    //计算矩阵相乘

    matrix multiply(matrix x,matrix y){

        matrix temp;

        memset(temp.a,0,sizeof(temp.a));

        for(int i = 0; i < n; i++){

            for(int j = 0; j < n ; j++){

                for(int k = 0; k < n; k++) {

                    temp.a[i][j] += x.a[i][k] * y.a[k][j];

                }

            }

        }

        return temp;

    }

    void quick_matrix(int m){

        while(m){

            if(m&1)  res = multiply(res,origin);

            m = m >> 1;

            origin = multiply(origin,origin);

        }

    }

    11)、欧拉函数

    //1--n-1所有与n互质的数的和为:Sum  = n*(eular(n)/2)

    //暴力求n互质的个数

    int eular(int n){

       int ret=1,i;

       for(i=2;i*i<=n;i++){

          if(n%i==0){

              n/=i;ret*=i-1;

              while(n%i==0) {

                  n/=i;ret*=i;

              }

          }

        }

        if(n>1) ret*=n-1;

        return ret;

    }

    //内存允许情况下

    LL prim[N], p[N];

    LL index;

    void find_prim()

    {

        index = 0;

        for(LL i = 2; i <= N; i++){

            if(!p[i]){

                prim[index++] = i;

                for(LL j = i+i; j <= N; j+=i){

                    p[j] = 1;

                }

            }

        }

    }

    LL enlur(LL a,LL index)

    {

        LL s = 1;

        if(a == 0)   return 0;

        LL i = 0 ,tt = 0;

        while(prim[i] < a && i < index){

            tt = 0;

            if(a%prim[i] == 0){

                while(a%prim[i] == 0){

                    a/=prim[i];

                    tt++;

                }

            }

            s *= tt+1;

            i++;

        }

        if(a > 1)  s *= 1+1;

        return s;

    }

    //优化一般首选,打印欧拉函数表

    __int64 phi[N]={0};

    void phi_table(){

        phi[1]=1;

        for(int i=2; i<=N; i++){

            if(!phi[i]){

                for(int j=i; j<=N; j+=i){

                    if(!phi[j]) phi[j]=j;

                    phi[j]=phi[j]/i*(i-1);

                }

            }

        }

    }

    12)、反素数

    //n以内因子最多的最小的那个X

    LL bestnum , maxsum , n;//bestnum最小的,maxsum因子个数

    LL prime[16] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};

    void dfs(LL index,LL temp,LL sum){

        if(temp > n) return;

        //sum记录当前的因子个数,maxsum小就更新

        if(sum > maxsum){

            maxsum = sum;

            bestnum = temp;

        }

         //当因子个数相同时,取值最小的

        if(sum == maxsum && bestnum > temp) bestnum = temp;

        for(LL i=1;i<=63;i++){

            if(n < temp*prime[index]) break;

            temp *= prime[index];//累乘到当前数

            dfs(index+1,temp,sum*(i+1));

        }

    }

    调用// dfs(0,1,1);

    //给一个数,求一个最小的正整数,使得它的因子个数为。

    LL maxsum,n;

    void dfs(int index,LL temp,int sum){

        if(sum > n) return;

        if(sum == n && maxsum > temp) maxsum = temp;

        for(int i=1;i<=63;i++){

            if(maxsum / prime[index] < temp || sum*(i+1) > n) break;

            temp *= prime[index];

            if(n % (sum*(i+1)) == 0)  dfs(index+1,temp,sum*(i+1));

        }

    }

    2、组合数学

    1)、错排

    选新娘问题,有NN<=20)对新人,其中有M个新郎找错新娘。问有多少种可能?

    代码:

    __int64 a[25];

    void init(){

    //这个是错排打表

        a[0] = 1; a[1]=0;  a[2]=1;

        for(i=3;i<=20;i++){

            a[i]=(i-1)*(a[i-1]+a[i-2]);

        }

    }

    __int64 Cmn(__int64 m, __int64 n){

         if( m==n || n == 0) return 1;

         LL s = 1 , t = 1;

         for(__int64 i = m; i > m - n; i--)   s *= i;

         for(__int64 i = 1; i <= n; i++)  t *= i;

         return s/t;

    }

    int main(){

        int tcase,m,n,i,j;

    __int64 sum;

    init();

    scanf("%d",&tcase);

        while(tcase--){

            scanf("%d%d",&m,&n);

            sum=Cmn(m,n)*a[n];//Cmn是组合

            printf("%I64d ",sum);

        }

        return 0;

    }

    2)、全排列

    直接用c++stl库里面的东西!输出的结果直接就是字典序

    sort(str,str+len);//这步是必须要的,先排序,len数组元素的长度

    cout<<str<<" 所有全排列的结果为:"<<endl;

    do{

    for(int i=0;i<len;i++)  cout<<str[i]<<” “;

    cout<<endl;

    }while(next_permutation(str,str+len));

    3)Cmn%p问题

    //小数据情况下a[N][m]即可

    void init(){

        int i,j;

        for(i=1;i<=N;i++){

            a[i][1]=i%p;

            a[i][0]=1;

        }

        for(i=2;i<=N;i++){

            for(j=1;j<=N;j++){

                a[i][j]=(a[i-1][j]+a[i-1][j-1])%p;//这个是公式

            }

        }

    }

    3、博弈论

    1)、威佐夫博奕(Wythoff Game

    有两堆各若干个物品,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。

    int m,n;//两堆石子个数

    while(cin>>m>>n)

    {

       int ans = floor(abs(m - n)*(1.0+sqrt(5.0))/2.0);

    if (ans == min(m,n)) cout<<0<<endl;

       else cout<<1<<endl;//   

    }

    2)、尼姆博奕(Nimm Game

    有三堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜。

        int m,p[101];

        while(cin>>m,m)

        {

            int ans=0;

            for(int i = 0; i < m; i++)

            {

                cin >> p[i];

                ans ^= p[i];

            }

            if(ans) cout << "Win" << endl;

            else cout << "Not win" << endl;

            //如果先手的人能赢,请输出他第一步可行的方案数,否则请输出0

            int s = 0;

            for(int i = 0; i < m; i++){

                if(p[i] > (p[i] ^ ans)  )s++;

            }

            cout<<s<<endl;

        }

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    Oracle数据库基础
    软件项目开发模式——三层模式
    JavaWeb——Ajax与MVC学习总结
    JavaWeb——EL及JSTL学习总结
    JavaWeb——过滤器及监听器
    JavaWeb——Servlet开发
  • 原文地址:https://www.cnblogs.com/gaojupeng/p/4730766.html
Copyright © 2011-2022 走看看