UVA 10717 - Mint

来源:互联网 发布:闪凌网络是真的吗 编辑:程序博客网 时间:2024/05/30 18:29

这道题本身并不是很难,其实就是求最小公倍数,具体来说就是求任意四种硬币厚度的最小公倍数,最小公倍数可以用欧几里德算法来求出LCM,(至于四个数的最小公倍数可以用四重for循环来求,好在本题数据不大,四重for循环总共C50,4=20300)然后只需找出最小的p,q,满足p*lcm<=h,q*lcm>=h,然后只需注意一点p可能为0;不过这道题貌似怎么些都不超时,写了三次,第一次加了好多优化,第二次去了一些仍然AC,第三次去掉所有优化,直接搜索,仍然AC,时间仍没超过1s,题目最大限制是3s,表示无语,不过第一次和第三次时间相差近20倍……
优化方法:1,可以在每重for循环后记忆下求出的最小公倍数(代码**处),2,在每重for循环后进行一下判断,如果还未到最后一重循环,而这几个数的最小公倍数已经比较大,就没必要在执行下一重循环,3,可以在第一重for判断这个coin的厚度是否可以被它后面那些整除,如果可以的话,则标记它后面整除它的那个数,下次遇到这个数就不必往后执行,因为此时如果算出最小公倍数的话,一定不如上次的最优;
下面是最后没优化的代码:
code:
#include<cstdio>
#include<cstdlib>
long long N, K;
long long C[110];
long long gcd(long long a, long long b)
{
    return b?gcd(b,a%b):a;
}
long long lcm(long long a, long long b)
{
    return a/gcd(a,b)*b;
}
int cmp(const void *a, const void *b)
{
    return *(long long *)a - *(long long *)b;
}
int Search(long long n)
{
    long long i,j,k,l,p,q,y,z;
    long long down = 10000000, up = 100000000;
    for(i = 0; i<= N-4; i++)
    {**
        for(j = i+1; j<=N-3; j++)
        {**
            for(k = j+1; k<=N-2; k++)
            {**
                for(l = k+1; l<N; l++)
                {**
                    y = lcm(C[l],lcm(C[k],lcm(C[j],C[i])));
                    q = (n/y);
                    p = n - q*y;
                    z = q*y + y;
                    if(p<down && y<=n) down = p;
                    if(z<up) up = z;
                }
            }
        }
    }
    if(down <1000000)
        printf(\"%lld\",n - down);
    else printf(\"0\");
    printf(\" %lld\\n\",up);
}


int main()
{
    long long i, n;
    //freopen(\"in.txt\",\"r\",stdin);
    //freopen(\"out.txt\",\"w\",stdout);
    while(scanf(\"%lld%lld\",&N,&K) == 2&&(N||K))
    {
        for(i = 0; i<N; i++)
            scanf(\"%lld\",&C[i]);
        qsort(C,N,sizeof(C[0]),cmp);
        while(K--)
        {
            scanf(\"%lld\",&n);
            long long  c = 0;
            int flag;
            for(i = 0; i<N; i++)
            {
                flag=0;
                if(C[i] && n%C[i] == 0) c++;
                if(c == 4)
                {
                    printf(\"%lld %lld\\n\",n,n);
                    flag=1;
                    break;
                }
            }
            if(flag)
                continue;
            Search(n);
        }
    }
    return 0;
}

原创粉丝点击