zoukankan      html  css  js  c++  java
  • acm数论之旅--唯一分解定理

    题目:
        给出n,问n = b^p中p符合该等式的最大值
    
    分析:
        先求出所有n的质因子,然后对这m个质因子分类统计,比如
        n = 36时,可以分成 2个2,2个3,然后求出所有这些基数的
        最大公因数gcd。另外由于有负数的存在,所以求到的gcd若
        为偶数时,需要不断除二直到为奇数为止

    根据完全P次方数的定义可知,一定会借助唯一分解定律,那么必然预处理素数表 。

    但是仅仅唯一分解还是不够的,要怎么求最大的幂呢?  我们来举几个例子,加入唯一分解成2   2   3,那么答案是1 , 如果 2  2  2  ,答案是3,如果 2  2  3  3  ,答案是2, 可以发现,其实答案就是各质数的指数的最大公约数。     但是WA了,因为题目并没有说输入的一定是正整数,而且给过提示 : 输入在32位有符号整数范围内。

    那么为什么负数会导致计算错误呢?  比如:-16 ,分解成4个2,但是没有一个整数可以表示出-16这个答案,因为偶次幂一定是正的。   所以,当n为负数时,答案不能为偶数。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn = 333333;
    ll n,m,vis[maxn+5]={0},prime[maxn+5],cnt=0;
    void init() {
        int m = sqrt(maxn);
        for(int i=2;i<=m;i++) if(!vis[i])
            for(int j=i*i;j<=maxn;j+=i) vis[j] = 1;
        for(int i=2;i<=maxn;i++)
            if(!vis[i]) prime[cnt++] = i;
     
    }
    ll gcd(ll a,ll b) {
        return b == 0 ? a : gcd(b, a%b);
    }
    ll solve(ll n) {
        bool ok = false;
        ll ans = 0,temp = n;
        for(int i=0;i<cnt;i++) {
            ll c = 0;
            while(n % prime[i] == 0) {
                n /= prime[i];
                c++;
            }
            ans = gcd(ans,c);
            if(n == 1) break;
        }
        if(ans == 0) ans = 1;
        if(temp < 0)
            while(ans % 2 == 0) ans /= 2;
        return ans;
    }
    int main() {
        init();
        while(~scanf("%lld",&n)&&n) {
            ll ans = solve(n);
            printf("%lld
    ",ans);
        }
        return 0;
    }


    n是大于一的任意正整数。(称为标准分解式)其中pi为素数,质数ai为正整数(如果ai=0,相当于乘一,没有意义的)。

    标准分解式是唯一且一定存在的。(素因子的乘积顺序不考虑)

    下面给出几个简单的判别式:

    整数a能被2整除的充要条件是a的末尾数字为偶数。
    整数a能被3整除的充要条件是a的各位数字之和能被3整除。
    整数a能被5整除的充要条件是a的末尾数字为0或5 。
    整数a能被11整除的充要条件是a的奇位数字之和(1.3….)和偶位数字之和(2.4…)的差的绝对值能被11整除。
    (很神奇)将a写成千进制数,即a=an*1000^n + an-1 *1000^n-1 + … + a1 *1000 + a0 ,其中0<=ai<1000,则a能被7(或11或13)整除的充要条件是(a0 + a2 + …) - (a1 + a3 + …) 能被7(或11或13)整除。
    暴力算法

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    
    using namespace std;
    const double eps = 0.001;  //用于浮点数精度控制
    int Cal(int n)
    {
        int i,j;
        for(i=30; i>=2; i--)
        {
            if(pow(2,i)  < n+eps)//不加会超时!
                for(j=2; j*j<=n; j++)
                {
                    double t = pow(j,i);
                    if(t > n-eps &&t < n+eps)
                        return i;
                    if(t > n+eps)//不加会超时,下个函数一样!
                        break;
                }
        }
        return 1;
    
    }
    int Cal2(int n)
    {
        int i,j;
        for(i=31; i>=3; i-=2)//偶数次方只可能是正数
        {
            if(pow(2,i) - eps < (double)(-n))
                for(j=2; j*j<=-n; j++)
                {
                    double t = pow(j,i);
                    if(t > -n-eps &&t < -n+eps)
                        return i;
                    if(t > -n+eps)
                        break;
                }
        }
        return 1;
    }
    int main()
    {
        int n,i;
        while(scanf("%d",&n) && n)
        {
            if(n==-2147483648)  //最小的int型数,防止越界就提出来特殊判断一下。
            {
                printf("31
    ");
                continue;
            }
            if(n>0)
                printf("%d
    ",Cal(n));
            else
                printf("%d
    ",Cal2(n));
        }
        return 0;
    }

    https://blog.csdn.net/u013555159/article/details/52101898

    给出一个数,求能够相乘得到他的数中,元素总和最小的一个,就是求他的质因子分解,如果只有一个质因子,那最后结果要加上1.

     
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    typedef unsigned long long ll;
    ll counter,r;
    ll init(ll n)
    {
        if(n==1) return 2;
        counter=0;
        r=0;
        ll temp=(int)((double)sqrt(n)+1);
        for(ll i=2;i<=temp;i++)
        {
            if(n%i==0)
            {
                ll ans=1;
                counter++;
                while(n%i==0)
                {
                    ans=i*ans;
                    n=n/i;
                }
                r+=ans;
            }
        }
        if(n!=1) {r+=n;counter++;}
        if(counter==1) return r+1;
        else return r;
    }
    int main(int argc, const char * argv[]) {
        //freopen("/Users/zhangjiatao/Documents/暑期训练/input.txt","r",stdin);
        ll n;
        int t=0;
        while(scanf("%lld",&n)==1)
        {
            //cout<<"shit"<<endl;
            if(n==0) break;
            t++;
            cout<<"Case "<<t<<": "<<init(n)<<endl;
        }
        return 0;
    }
  • 相关阅读:
    推荐一个学习 SharePoint 2010 的站点
    应用反射技术为Infragistics Solution设计例子程序 代码简洁而且学习的效率高
    .NET程序员掌握的.NET技术
    Jpegoptim Tool
    Stack Overflow 漫谈
    NServiceBus最流行的开源企业服务总线AND让创建企业级.NET系统更加容易
    步步为营UML建模系列四、状态图(State)
    Web中的幻灯片组件实现
    轻轻松松SOA: NServiceBus
    细说 ASP.NET Cache 及其高级用法
  • 原文地址:https://www.cnblogs.com/downrainsun/p/9800401.html
Copyright © 2011-2022 走看看