欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

搞定B题!常见公约数(Codeforces):数论算法基本定理和唯一分解定理模板

最编程 2024-02-04 09:19:09
...
Output
4

求一组数的共同因数的数目。
  看数据,暴力一个一个看肯定超时。脑子跟猪一样,看完这个题,我的第一反应,竟然只知道这些因数一定小于最小的数(废话)。结果思维一直限制,绕在里面出不来。
打了一年了,自己还是....唉,努力训练吧,上题解。
以下两种解法都需要求出这组数的最大公因数。为什么呢,找到总的最大公因数N,那么剩下的公因数一定小于它。竟然这组数可以整除N,那么也一定可以整除N的因数。
接下来的工作,就是找N的因数个数。
解法一:直接找,但是不能暴力一个一个for,还是会超时。要知道,一个数N的因数,以sqrt(N)为分界线,一半在左,一半在右。所以我们只需求出<sqrt(n)的部分ans,
ans*2,然后对sqrt(N)特判一下,看看,是否(int)sqrt(N)*(int)sqrt(N)==N.
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn=4e5+10;
ll tot=0;
ll a[maxn];
ll cha[maxn];
ll b[maxn];
int main()
{ 
     ll n;
     while(cin>>n)
     {
         for(int i=0;i<n;i++)
             scanf("%lld",&a[i]);
         ll k=a[0];
         for(int i=1;i<n;i++)
             k=__gcd(k,a[i]);
         if(k==1)
         {
             printf("1\n");
             continue;
         }
        double mid=sqrt(k);
        ll ans=0;
        for(int i=1;i<mid;i++)
        {
            if(k%i==0)
                ans++;
        }
        ans*=2;
        if((int)mid*mid==k)
            ans++;
        cout<<ans<<endl;
     }
}
解法二:数论。算术基本定理(摘自****):

 所以对N进行分解:

ll ans=1;
        for(ll i=2;i*i<=t;i++)
        {
            if(t%i==0)
            {
                ll cnt=0;
                while(t%i==0)
                {
                    t=t/i;
                    cnt++;
                }
                ans=ans*(cnt+1);
            }
        }
        if(t>1)//别忘了加
            ans*=2;
//算是唯一分解定理的一个模板
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn=4e5+10;
ll a[maxn];
int main()
{ 
     ll n;
     cin>>n;
     for(int i=0;i<n;i++)
         cin>>a[i];
     ll t=a[0];
     for(int i=1;i<n;i++)
         t=__gcd(t,a[i]);
    if(t==1)
        cout<<"1"<<endl;
    else
    {
        ll ans=1;
        for(ll i=2;i*i<=t;i++) 
        {
            if(t%i==0)
            {
                ll cnt=0;
                while(t%i==0)
                {
                    t=t/i;
                    cnt++;
                }
                ans=ans*(cnt+1);
            }
        }
        if(t>1)
            ans*=2;
        cout<<ans<<endl;
    }
}

不多说,接着训练!不给自己的acm生涯留遗憾!