首页 文章

Euler的Totient函数置换

提问于
浏览
0

我在SPOJ上做了这个问题 . www.spoj.com/problems/TIP1 . 我已经写了这段代码,但是在判断时我超出了时间限制 . 任何人都可以帮助我进行任何优化或更好的方法 .

如果N是正整数,则PHI(N)是GCD(N,K)= 1且1≤K≤N的整数K.我们将GCD表示为最大公约数 . 例如,我们有PHI(9)= 6 .

#include<iostream>
#include<vector>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;

#define N 10000010
#define MAXN 10000010
int phi[MAXN + 1], prime[MAXN/10], sz=0;
vector<bool> mark(MAXN + 1);

int ans[10000011];
vector<int> a(10);
vector<int> b(10);

bool isprm(long int x)
{

for(int s=0; s<10; s++)
{
    a[s]=b[s]=0;
}
long int y=phi[x];
int i=0,j=0;
while(x>0)
{
    int rem=x%10;
    x=x/10;
    a[i]=rem;
    i++;
}

    while(y>0)
{
    int rem=y%10;
    y=y/10;
    b[j]=rem;
    j++;
}


sort(a.begin(), a.end());
sort(b.begin(), b.end());


if(i!=j)
return false;

for(int s=0; s<10; s++)
{
    if(a[s]!=b[s])
    return false;
}

return true;
}

void precompute_again()
{
for(int i=0; i<=20; ++i)
ans[i]=0;

ans[21]=21;

for(long int i=22; i<10000005; ++i){
bool chk=false;

chk=isprm(i);

if(chk==true)
{

    if(i*phi[ans[i-1]]==phi[i]*ans[i-1])
    {
        ans[i]=i;
    }
    else
    {

            if(i*phi[ans[i-1]]>phi[i]*ans[i-1])
            {
                ans[i]=ans[i-1];
            }
            else
            {
                ans[i]=i;
            }

    }
}
else
{
        ans[i]=ans[i-1];

}

}


}

int main()
{

phi[1] = 1; 
for (int i = 2; i <= MAXN; i++ ){
if(!mark[i]){
    phi[i] = i-1;
    prime[sz++]= i;
}
for (int j=0; j<sz && prime[j]*i <= MAXN; j++ ){
    mark[prime[j]*i]=1;
    if(i%prime[j]==0){
        int ll = 0;int xx = i;
        while(xx%prime[j]==0)
        {
                       xx/=prime[j];
                       ll++;         
                   }
        int mm = 1;
        for(int k=0;k<ll;k++)mm*=prime[j];
        phi[i*prime[j]] = phi[xx]*mm*(prime[j]-1);
        break;
 }
    else phi[i*prime[j]] = phi[i]*(prime[j]-1 );
 }
 }


precompute_again(); 

int t;
scanf("%d",&t);
while(t--)
{
long int m;
scanf("%ld",&m);
cout<<ans[m]<<endl;
}
return 0;    
}

1 回答

  • 1

    尝试使用Sieve of Eratosthenes的变体 .

    以下代码计算 phi[N]MAXN . 对于 MAXN = 1e7 ,它眨眼间就会运行 .

    int i, j;
    int * phi = new int [MAXN];
    for (i = 1; i < MAXN; i ++)
        phi[i] = i;
    
    for (i = 2; i < MAXN; i ++)
    {
        if (phi[i] != i) continue;
        for (j = i; j < MAXN; j += i)
            phi[j] = phi[j] / i * (i - 1);
    }
    

相关问题