zoukankan      html  css  js  c++  java
  • 【(阶乘的质因数分解)算组合数】【TOJ4111】【Binomial efficient】

    n<=10^6

    m<=10^6

    p=2^32


    用unsigned int 可以避免取模


    我写的SB超时 阶乘分解代码

    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <string>
    #define oo 0x13131313
    using namespace std;
    const unsigned int N=1000000+5;
    unsigned int tag[N],p[N],z[N],mm[N];
    unsigned int cnt = 0;
    unsigned int n,m;
    unsigned int quickpow(unsigned int m,unsigned int n)
    {
        unsigned int b = 1;
        while (n > 0)
        {
              if (n & 1)
                 b = (b*m);
              n = n >> 1 ;
              m = (m*m);
        }
        return b;
    }
    
    void get_prime()
    {
        tag[1]=1;
        tag[0]=1;
        for (unsigned int i = 2; i < N; i++)
        {
            if (!tag[i])    p[cnt++] = i;
            for (unsigned int j = 0; j < cnt && p[j] * i < N; j++)
            {
                tag[i*p[j]] = 1;
                if (i % p[j] == 0)
                    break;
            }
        }
    }
    unsigned int FIND(unsigned int x)
    {
        unsigned int l=0,r=cnt-1;
        while(l<=r)
        {
            unsigned int m=(l+r)/2;
            if(p[m]==x) return m;
            else if(p[m]<x) l=m+1;
            else r=m-1;
        }
    }
    void fenjie(unsigned int *a,unsigned int d)
    {
        for(unsigned int i=0;i<cnt&&p[i]<=sqrt(d);i++)
        {
            while(d%p[i]==0)
            {
                d=d/p[i];
                a[i]++;
            }
        }
        if(tag[d]==0)
        {
            unsigned int t=FIND(d);
            a[t]++;
        }
    }
    int main()
    {
       // freopen("a.in","r",stdin);
        get_prime();
        int T;
        cin>>T;
        while(T--)
        {
            cin>>n>>m;
            memset(z,0,sizeof(z));
            memset(mm,0,sizeof(mm));
            for(unsigned int i=n;i>=n-m+1;i--)
                fenjie(z,i);
            for(unsigned int i=1;i<=m;i++)
                fenjie(mm,i);
            unsigned int ans=1;
            for(unsigned int i=0;i<cnt;i++)
                {
                    z[i]=z[i]-mm[i];
                    ans=ans*quickpow(p[i],z[i]);
                }
            printf("%u
    ",ans);
        }
    }
    

    利用阶乘的质因数分解!


    比如250!


    1*2*3*4*5*6*7*8*9*10*11*12*13*14.....250

    中3的质因子个数 除了3后变成(不是倍数的不管)计算3^1次方的为250/3个

    又变成 1 2 3 .....250除3  

    重复上面 知道 3^2 为250/(3^2) 


    所以阶乘的质因数分解是另外的简单算法

    void getcn(int n)
    {
    	int ans = 0;
    	int i;
    	for (i = 1; i <= prime[0] && prime[i] <= n; i++)
    	{
    		int tmp = n;
    		while (tmp)
    		{
    			num[i] += tmp / prime[i];
    			tmp /= prime[i];
    		}
    	}
    	num[0] = i;
    }
    

    所以最后的代码是

    #include <string.h>
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <string>
    #include <algorithm>
    #include <vector>
    #include <string.h>
    #include <time.h>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #include <sstream>
    #define INF 0x3f3f3f3f
    #define MAXN 1000005
    #define Precision 100005
    #define MAX_INT 2147483647
    #define Pi acos(-1.0)
    #define lowbit(x) ((x)&(-x))
    #define Lson root<<1,left,mid
    #define Rson root<<1|1,mid+1,right
    #define LL long long
    #define ULL unsigned long long
    #define fresh(x) memset(x,0,sizeof(x))
    using namespace std;
    
    
    int prime[MAXN];
    int num[MAXN];
    
    
    void print()
    {
    <span style="white-space:pre">	</span>memset(prime, 0, sizeof(prime));
    <span style="white-space:pre">	</span>for (int i = 2; i <= 1000000; i++)
    <span style="white-space:pre">	</span>{
    <span style="white-space:pre">		</span>if (!prime[i]) prime[++prime[0]] = i;
    <span style="white-space:pre">		</span>for (int j = 1; j <= prime[0] && prime[j] <= 1000000 / i; j++)
    <span style="white-space:pre">		</span>{
    <span style="white-space:pre">			</span>prime[prime[j]*i] = 1;
    <span style="white-space:pre">			</span>if (i % prime[j] == 0) break;
    <span style="white-space:pre">		</span>}
    <span style="white-space:pre">	</span>}
    }
    
    
    unsigned qpow(unsigned a, unsigned b)
    {
    <span style="white-space:pre">	</span>unsigned ans = 1;
    <span style="white-space:pre">	</span>while (b)
    <span style="white-space:pre">	</span>{
    <span style="white-space:pre">		</span>if (b & 1)
    <span style="white-space:pre">			</span>ans *= a;
    <span style="white-space:pre">		</span>b >>= 1;
    <span style="white-space:pre">		</span>a *= a;
    <span style="white-space:pre">	</span>}
    <span style="white-space:pre">	</span>return ans;
    }
    
    
    void getcn(int n)
    {
    <span style="white-space:pre">	</span>int ans = 0;
    <span style="white-space:pre">	</span>int i;
    <span style="white-space:pre">	</span>for (i = 1; i <= prime[0] && prime[i] <= n; i++)
    <span style="white-space:pre">	</span>{
    <span style="white-space:pre">		</span>int tmp = n;
    <span style="white-space:pre">		</span>while (tmp)
    <span style="white-space:pre">		</span>{
    <span style="white-space:pre">			</span>num[i] += tmp / prime[i];
    <span style="white-space:pre">			</span>tmp /= prime[i];
    <span style="white-space:pre">		</span>}
    <span style="white-space:pre">	</span>}
    <span style="white-space:pre">	</span>num[0] = i;
    }
    
    
    void getcm(int m)
    {
    <span style="white-space:pre">	</span>int ans = 0;
    <span style="white-space:pre">	</span>int i;
    <span style="white-space:pre">	</span>for (i = 1; i <= prime[0] && prime[i] <= m; i++)
    <span style="white-space:pre">	</span>{
    <span style="white-space:pre">		</span>int tmp = m;
    <span style="white-space:pre">		</span>while (tmp)
    <span style="white-space:pre">		</span>{
    <span style="white-space:pre">			</span>num[i] -= tmp / prime[i];
    <span style="white-space:pre">			</span>tmp /= prime[i];
    <span style="white-space:pre">		</span>}
    <span style="white-space:pre">	</span>}
    }
    
    
    int main()
    {
    <span style="white-space:pre">	</span>int n, m, T;
    <span style="white-space:pre">	</span>print();
    <span style="white-space:pre">	</span>//printf("%d
    ", prime[prime[0]]);
    <span style="white-space:pre">	</span>//cout << prime[0];
    <span style="white-space:pre">	</span>scanf("%d", &T);
    <span style="white-space:pre">	</span>while (T--)
    <span style="white-space:pre">	</span>{
    <span style="white-space:pre">		</span>memset(num, 0, sizeof(num));
    <span style="white-space:pre">		</span>scanf("%d%d", &n, &m);
    <span style="white-space:pre">		</span>getcn(n);
    <span style="white-space:pre">		</span>getcm(m);
    <span style="white-space:pre">		</span>getcm(n - m);
    <span style="white-space:pre">		</span>unsigned ans = 1;
    <span style="white-space:pre">		</span>for (int i = 1; i <= num[0]; i++)
    <span style="white-space:pre">		</span>{
    <span style="white-space:pre">			</span>ans *= qpow(prime[i], num[i]);
    <span style="white-space:pre">		</span>}
    <span style="white-space:pre">		</span>printf("%u
    ", ans);
    <span style="white-space:pre">	</span>}
    <span style="white-space:pre">	</span>return 0;
    }
    


  • 相关阅读:
    LR11
    安装Nginx+uWSGI+Django环境
    MYSQL 安装更新,使用,管理,备份和安全等
    oracle里要查看一条sql的执行情况,有没有走到索引,怎么看?索引不能提高效率?
    大神:python怎么爬取js的页面
    Sublime 编译出来的是 dos格式,不是unix格式
    前天搞了一天?昨天搞了一天?今天搞了半小时
    搞了一宿,弄完了一个POP3协议
    我竟然。。。傻了近一年
    跨进程信息交互真个费事。
  • 原文地址:https://www.cnblogs.com/zy691357966/p/5480337.html
Copyright © 2011-2022 走看看