Codeforces Round #502 (Div. 1 + Div. 2)F. The Neutral Zone(分段筛)

题意

  我们知道, log(p1a1p2a2p3a3...)=a1logp1+a2logp2+... l o g ( p 1 a 1 p 2 a 2 p 3 a 3 . . . ) = a 1 l o g p 1 + a 2 l o g p 2 + . . . (其中p为质数)
   p1a1p2a2p3a3... p 1 a 1 p 2 a 2 p 3 a 3 . . . 为 一 个 数 的 质 因 数 分 解 的 表 示 形 式 。
  现在我们定义 exlog(p1a1p2a2p3a3...)=a1f(p1)+a2f(p2)+... e x l o g ( p 1 a 1 p 2 a 2 p 3 a 3 . . . ) = a 1 f ( p 1 ) + a 2 f ( p 2 ) + . . .
  其中 f(x) f ( x ) 为一个次数不超过3次的多项式,即 f(x)=Ax3+Bx2+Cx+D f ( x ) = A x 3 + B x 2 + C x + D
  注意到exlog(1)永远等于0。
  现在给出 n,A,B,C,D n , A , B , C , D ,求 i=1nexlog(i) ∑ i = 1 n e x l o g ( i )
  注意Memory Limit为16M

分析

  首先我们考虑,对于一个质数,他跟其他的质数是没有联系的。所以我们可以考虑每个质数 p p 对答案的贡献。他的k次即 kf(p) k ∗ f ( p ) 对答案的贡献为 npk ⌊ n p k ⌋ 次。那么我们最主要的就是如何筛素数了。直接筛肯定筛不出来,只能通过埃氏筛区间筛出来,因为埃氏筛可以只记录一个划掉的数的表。这样我们就可以做完这道题了。

Code

#pragma GCC optimize(3)
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
/*================Header Template==============*/
int n,cnt,prime[200005],lim,tmp,l,r;
unsigned A,B,C,D,res;
bool b[2000005];
inline void sieve() {
    for(int i=2;i<=30000;i++) {
        if(!b[i]) {
            prime[++cnt]=i;
            for(int j=i+i;j<=30000;j+=i)
                b[j]=1;
        }
    }
    lim=3e8,l=2,r=tmp=2000000;
}
inline void Sieve() {
    memset(b,0,sizeof(b));
    for(int i=1;i<=cnt;i++) {
        int x=prime[i];
        for(int j=max(2,l/x+!!(l%x))*x;j<=r;j+=x)
            b[j-l]=1;
    }
}
inline unsigned getans(unsigned x) {
    unsigned val=A*x*x*x+B*x*x+C*x+D,ans=0;
    long long now=x;
    while(now<=n)
        ans+=val*(n/now),now*=x;
    return ans;
}
inline void solve() {
    for(int i=l;i<=r;i++)
        if(!b[i-l])
            res+=getans(i);
}
inline void work() {
    while(l<=n) {
        Sieve();
        solve();
        l=r+1,r=l+tmp-1;
    }
}
int main() {
    read(n),read(A),read(B),read(C),read(D);
    sieve();
    work();
    printf("%u\n",res);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值