UVA11426 FZU1969 51NOD1188 线性欧拉筛法+筛法

题目大意

计算:

G=i<Ni=1j<=Nj=i+1GCD(i,j)


难度系数(往下递增):

  • UVA11426
  • FZU1969
  • 51NOD1188

题目思路一:

G=ng=1g(phi(gd1)

求这么个东西,我们先预处理欧拉函数,然后枚举公约数g。

显然对于 gd 我们可以分块求。

时间复杂度:

O(T*sqrt(n))


题目思路二:

因为51NOD,其样例数过多,那么我们就要想一种更快的办法。现在我们需要枚举公约数g,计算一下他们对其的倍数的贡献。然后在nlogn的时间里预处理出res[i](答案数组)。

伪代码:

    for(int g=1;g2;g++) 
        for(int i=g+g;i*phi[i/g];

时间复杂度:

O(nlogn+T)

( Orz 恩,这个做法感觉合理多了呢? )

代码如下:

#include
using namespace std;
typedef long long LL;
const int maxn=5e6+5;
int phi[maxn],prime[maxn],primesize;
LL res[maxn];
bool isprime[maxn];
const int read()  
{  
    char ch = getchar();  
    while (ch<'0' || ch>'9') ch = getchar();  
    int x = ch - '0';  
    while ((ch = getchar()) >= '0'&&ch <= '9') x = x * 10 + ch - '0';  
    return x;  
}  
template <class T>
inline void print_d(T x)
{
    if (x > 9)
    {
        print_d(x / 10);
    }
    putchar(x % 10 + '0');
}
int main()
{
    for(int i=2;iif(!isprime[i])
        {
             prime[++primesize]=i;
             phi[i]=i-1;
         }
         for(int j=1;j<=primesize&&i*prime[j]true;
            if(i%prime[j]==0)
             {
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
    for(int g=1;g2;g++) for(int i=g+g;i0]=0;
    for(int i=1;i1];
    int n,T;
    T=read();
    while(T--) 
    {
        n=read();
        print_d(res[n]);
        putchar('\n');
    }
}

你可能感兴趣的:(markdown,数论)