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;g<maxn/2;g++) 
        for(int i=g+g;i<maxn;i+=g) 
            res[i]+=(LL)g*phi[i/g];

时间复杂度:

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

代码如下:

#include<bits/stdc++.h>
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;i<maxn;i++)
    {
        if(!isprime[i])
        {
             prime[++primesize]=i;
             phi[i]=i-1;
         }
         for(int j=1;j<=primesize&&i*prime[j]<maxn;j++)
         {
            isprime[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;g<maxn/2;g++) for(int i=g+g;i<maxn;i+=g) res[i]+=(LL)g*phi[i/g];
    res[0]=0;
    for(int i=1;i<maxn;i++) res[i]+=res[i-1];
    int n,T;
    T=read();
    while(T--) 
    {
        n=read();
        print_d(res[n]);
        putchar('\n');
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值