Uva10791 Minimum Sum LCM

看同学的紫书(刘汝佳那本),还给人弄对了

真是衰呀。


昨天同学出来这么一道原题。

首先,对于质数,答案肯定是质数+1。这个可以miller-Rabin一波。

考虑合数,我们可以选择直接构造解。

如何构造?

首先这个肯定是质因数分解。然后在组合。如何组合?

首先我们很明白的算出来,在答案的可重集中。质因子不可能单独出现,或出现次数少于分解后他的幂。

如果此类情况发生,则lcm不为输入。

那么接下来就是考虑如何组合。

对于\(A>B\),有\(AB>B^2\)

所以肯定是这些质因子的幂的和。

所以答案就出来了

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
long long num[10]={0,2,3,5,7,11,13,17,19};
long long kasumi(long long a,long long b,long long p)
{
    long long ans=1;
    a=a%p;
    while(b)
    {
        if(b&1)
            ans=(ans*a)%p;
        b>>=1;
        a=(a*a)%p;
    }
    return ans;
}
bool test(long long val)
{
    if(val==2)
        return true;
    if(val%2==0||val==1)
        return false;
    for(int i=1;i<=8;i++)
        if(val==num[i])
            return true;
    long long t=0,tmp=val-1,now;
    while((tmp&1)==0)
    {
        tmp>>=1;
        t+=1;
    }
    for(int i=1;i<=8;i++)
    {
        now=kasumi(num[i],tmp,val);
        long long nxt=now;
        for(int i=1;i<=t;i++)
        {
            nxt=(now*now)%val;
            if(nxt==1&&now!=1&&now!=val-1)
                return false;
            now=nxt;
        }
        if(now!=1)
            return false;
    }
    return true;
}
int main()
{
    int AA=0;
    //scanf("%d",&t);
    long long a;
    scanf("%lld",&a);
    while(a)
    {
    	AA++;
        if(test(a)||a==1)
        {
            printf("Case %d: %lld\n",AA,a+1);
            scanf("%lld",&a);
            continue;
        }
        long long sum=0;
        int T=0;
    	for(int i=2,t=0;i*i<=a;i++)
    		if(a%i==0)
    		{
    			T++;
    			long long pas=1;
    			while(a%i==0)
    			{
    				a/=i;
    				pas*=i;
                }
                sum+=pas;
            }
        if(a!=1)	sum+=a;
        if(T==1&&a==1)
            printf("Case %d: %lld\n",AA,sum+1);
        else
            printf("Case %d: %lld\n",AA,sum);
        scanf("%d",&a);
    }
}
posted @ 2018-11-08 08:56  Lance1ot  阅读(95)  评论(0编辑  收藏  举报