为什么spoj为Euler Totient函数的这个解决方案提供了错误的答案?

时间:2014-06-10 14:50:58

标签: c algorithm primes

我正在解决SPOJ的ETF问题。我正在使用eratosthenes方法筛来计算质数,然后使用Phi的基本定义,但是SPOJ给出了错误的答案。我在GCC编译器上测试了它,在那里提到了0到1000,000的范围。但无法找到错误。 我知道查看别人的代码有点痛苦,但我真的很感激任何帮助。

#include<stdio.h>
#include<string.h>
#include<math.h>
#define PRIME_COUNT 2000

int main()
{
        long unsigned int number;
        long sieveArray[PRIME_COUNT],primes[PRIME_COUNT],prime_count=0;
        int i=2,j,test_cases;
        long phi, tempNumber;

        memset(sieveArray,0,PRIME_COUNT*sizeof(long));

        while(1)
        {
                if(i>PRIME_COUNT)
                        break;
                if(sieveArray[i]==0)
                {
                        primes[prime_count++]=i;
                        for(j=i;j<PRIME_COUNT;j=j+i)
                        {
                                sieveArray[j]=1; 
                        }
                }
                i++;
        }


        scanf("%d",&test_cases);

        for(i=0;i<test_cases;i++)
        {
                scanf("%ld",&number);

                if(number!=0)
                {
                        phi=number;
                        tempNumber=number;
                        for(j=0;primes[j]*primes[j]<=tempNumber;j++)
                        {
                                if(tempNumber%primes[j]==0)
                                {
                                        phi*=(primes[j]-1);
                                        phi/=primes[j];
                                        while(tempNumber%primes[j]==0)
                                                tempNumber=tempNumber/primes[j];
                                }
                        }
                        if(tempNumber!=1)
                        {
                                phi*=(tempNumber-1);
                                phi/=tempNumber;
                        }
                }
                else 
                        phi =number;

                printf("%ld\n",phi);
        }
        return 0;
}

1 个答案:

答案 0 :(得分:0)

将您的long更改为long long,或者更改

的顺序
                            phi*=(tempNumber-1);
                            phi/=tempNumber;

                            phi/=tempNumber;
                            phi*=(tempNumber-1);

(以及所有其他类似的行)将临时值保存在数据类型的边界内。首先删除,然后才增加。要了解原因,请考虑number是否位于最高限额以下的素数时的情况。

顺便提一下,当您if(sieveArray[i]==0)时,sieveArray[PRIME_COUNT]会尝试访问i==PRIME_COUNT数组的一个结尾元素。