Min_25筛代码

Sn=i=1nfi S n = ∑ i = 1 n f i

Fn=i=1n[i]fi F n = ∑ i = 1 n [ i 为 质 数 ] f i

Sn,k=i=kj=1[npj+1i](Snpji,i+1fpji+fpj+1i)+FnFpk1 S n , k = ∑ i = k ∑ j = 1 [ n ≤ p i j + 1 ] ( S n p i j , i + 1 f p i j + f p i j + 1 ) + F n − F p k − 1

偷懒写了更容易的写法,跑的慢一些

#include<cstdio>
#include<algorithm>
#include<cstring>
#define rep(a,b,c) for (int a=b;a<=c;a++)
#define per(a,b,c) for (int a=b;a>=c;a--)
#define go(u) for (int o=ft[u],v;v=E[o].t;o=E[o].n)
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int,int> par;
typedef double dob;
const int N=2000100,P=1000000007;
LL n,g[N],pr[N/10];
int pt,sum,magic;
struct dat{
    LL d,r;// iff d<magic d is right    n/d=r
    inline int id(){return r<=magic?r:sum+1-d;}
    dat operator /(LL k){return (dat){d*k,r/k};}
}num[N];
LL calc(dat n,int k){
    if (pr[k]>n.r) return 0;
    LL ans=g[n.id()]-g[pr[k]-1];
    rep(i,k,pt){
        LL p=pr[i];
        if (p*p>n.r) break;
        for (LL j=1,np=p;n.r>=np*p;++j,np*=p){
            ans+=calc(n/np,i+1)*(j<<1|1)/* f[np] */+(j*2+3)/* f[np*p] */;//,ans%=P;
        }
    }
    return ans;
}
void work(){
//  freopen("t.txt","r",stdin);
    scanf("%lld",&n);
    pt=0;
    for (magic=1;(LL)magic*magic<=n;magic++);
    rep(i,1,magic) num[i]=(dat){0,i};
    sum=magic;
    rep(i,1,n){
        if (n/i<=magic) break;
        num[magic+i]=(dat){i,n/i};
        sum=magic+i;
    }
    rep(i,magic+1,sum){
        if (i>=sum+magic+1-i) break;
        swap(num[i],num[sum+magic+1-i]);
    }
    rep(i,1,sum) g[i]=num[i].r*3-3;
    rep(p,2,magic){
        if (g[p]==g[p-1]) continue; // not a prime
        pr[++pt]=p;
        per(j,sum,1){
            if ((LL)p*p>num[j].r) break;
            g[j]-=g[(num[j]/p).id()]-g[p-1]; // -=( )*p^k
        }
    }
    pr[pt+1]=magic+1;
//  rep(i,1,sum) g[i]%=P;
    LL ans=calc(num[min((LL)sum,n)],1)+1;
//  ans=(ans%P+P)%P;
    printf("%lld\n",ans);
}
int main(){
    int tc;
    scanf("%d",&tc);
    while (tc--) work();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值