zoukankan      html  css  js  c++  java
  • gcd和lcm在分解质因子的应用

    lcm:

    传送门

    找到以下代码的结果:

    long long pairsFormLCM( int n ) {
        long long res = 0;
        for( int i = 1; i <= n; i++ )
            for( int j = i; j <= n; j++ )
               if( lcm(i, j) == n ) res++; // lcm means least common multiple
        return res;
    }

    代码的直接实现可能会超时。如果您分析代码,您将发现代码实际上计数lcm(i, j) = n和(i≤j)的对(i, j)的数量。

    输入

    输入以整数T(≤200)开始,表示测试用例的数量。

    每一种情况都以包含整数n(1≤n≤1014)的行开始。

    输出

    对于每种情况,打印大小写和函数'pairsFormLCM(n)'返回的值

     lcm是max(a1,b1)的最大值,gcd是最小值min(a1,b1)

    上面是lcm 的性质。 现在考虑怎么计算。
    因为lcm是质因子的指数取max,那么也就是说。
    对于某一个质因子px i,j里面 必然有一个指数要等于 n的指数 也就是cx。 另外一个呢,[0-cx] 任选一个都行,总共cx+1 种可能。
    那么如果不考虑,i,j 的大小,即 j 可以小于 i,那么对于这一个质因子,方案数就是2*cx+1。

    对于其中的一项pi^ai来说,选择的两个数之一必须包含它,另外一个随意。。

    对于 ai == ei 时候, bi 可取 [0 ei] 共 1+ei 个情况

    ai < ei 时 bi 只可取 ei , ai 可取 [0, ei) 共  ei 个情况

    合起来共有 2ei+1 

    都取max(a,b) 的时候算了1次,而且ab ba是一种情况,所以我们还需要 +1之后再/2(先/2的话会默认向下取整出现问题)

    答案就显而易见了。

    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll; 
    const int maxn=1e7+100;
    bool biaoji[maxn];
    int prime[maxn/10];
    int cnt=0; 
    void inint(){
        for(int i=2;i<maxn;i++){
            if(!biaoji[i]) prime[++cnt]=i;
            for(int j=1;j<=cnt&&i*prime[j]<maxn;j++){
                biaoji[i*prime[j]]=1;
                if(i%prime[j]==0){
                    break;
                } 
            }
        }
    }
    ll n;
    ll t;
    int main(){
        cin>>t;
        inint();
        int kase=1;
        while(t--){    
            scanf("%lld",&n);
            ll ans=1;
            for(int i=1;i<=cnt;i++){
                if(1ll*prime[i]*prime[i]>n){
                    break;
                }
                ll p=0;
                while(n%prime[i]==0){
                    n/=prime[i];
                    p++;
                }
                if(p){ 
                    ans*=(p*2+1); 
                } 
            }
            if(n>1){
                ans*=3;
            }
            printf("Case %d: %lld
    ",kase++,(ans+1)/2);
        }
    }

    ​gcd

    传送门

    求满足条件的最大的指数p,使得a^p = x(a是整数)

    Input

    输入包含多组样例T(T<=50),每个样例包括一个整数x,x的范围在32位二进制数以内, 保证x的绝对值大于等于2。

    Output

    对于每个样例输出最大的指数p。

    Sample Input

    3

    17

    1073741824

    25

    Sample Output

    Case 1: 1

    Case 2: 30

    Case 3: 2

    x = p1^x1*p2^x2*p3^x3*...*ps^xs

    x = b^p, x只有一个因子的p次幂构成

    如果x = 12 = 2^2*3^1,要让x = b^p,及12应该是12 = 12^1

    所以p = gcd(x1, x2, x3, ... , xs);

    比如:24 = 2^3*3^1,p应该是gcd(3, 1) = 1,即24 = 24^1

             324 = 3^4*2^2,p应该是gcd(4, 2) = 2,即324 = 18^2

    本题有一个坑,就是x可能为负数,如果x为负数的话,x = b^q, q必须使奇数,所以将x转化为正数求得的解如果是偶数的话必须将其一直除2转化为奇数

    求x=bp中最大的p,x可能为负数。
    
    因数分解,x=p1x1*p2x2*...*pnxn
    
                      x=(p1x1‘*p2x2‘*...*pnxn‘)q
    
      如果x是正数的话,那么这个q最大就是gcd(x1,x2...xn),也就是答案了。
    
      如果x是负数,那么q显然应该是个奇数,让求得的q不断/2直至为奇数即可。
    
      题目明明说了x的范围在32为之内搞不懂为什么开LL才能过c。
    View Code

    代码:

    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+100;
    bool biaoji[maxn];
    int prime[maxn];
    int cnt=0; 
    int p[maxn];
    int c[maxn];
    void inint(){
        for(int i=2;i<maxn;i++){
            if(!biaoji[i]) prime[++cnt]=i;
            for(int j=1;j<=cnt&&i*prime[j]<maxn;j++){
                biaoji[i*prime[j]]=1;
                if(i%prime[j]==0){
                    break;
                }
            } 
        }
    }
    int gcd(int a,int b){
        if(b==0){
            return a;
        }
        else{
            return gcd(b,a%b);
        }
    } 
    int main(){
        int t;
        ll n;//注意开ll因为负数会爆 
        inint();
        cin>>t;
        int kase=1;
        while(t--){
            cin>>n;
            int flag=0;
            if(n<0){
                flag=1;
                n=-n;
            }
            int cot=0;
            for(ll i=1;i<=cnt&&prime[i]*prime[i]<=n;i++){
                if(n%prime[i]==0){
                    c[++cot]=0; 
                    p[cot]=i;
                    while(n%prime[i]==0){
                        c[cot]++;
                        n/=prime[i];
                    }
                } 
            }
            if(n>1){
                c[++cot]=1;
                p[cot]=n;
            }
            int ans=c[1];
            for(int i=2;i<=cot;i++){
                ans=gcd(ans,c[i]);
            } 
            if(flag){
                while(ans%2==0){
                    ans>>=1;
                }
            }
            printf("Case %d: %d
    ",kase++,ans);
        }
    } 
  • 相关阅读:
    c# 扩展方法奇思妙用
    AnkhSVN的自动加锁
    C#数组学习
    同一IP下多端口网站共享cookie的问题
    瞎子摸象销售开票(一)
    瞎子摸象年结
    配置WSS3.0搜索功能的步骤
    瞎子摸象销售开票(二)
    瞎子摸象汇兑损益
    ajax+php鼠标拖动层至任意位置并实时保存
  • 原文地址:https://www.cnblogs.com/lipu123/p/13900027.html
Copyright © 2011-2022 走看看