Min_25篩代碼

Sn=i=1nfi

Fn=i=1n[i]fi

Sn,k=i=kj=1[npij+1](Snpij,i+1fpij+fpij+1)+FnFpk1

偷懶寫了更容易的寫法,跑的慢一些
#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章