min_25筛:DIVCNTK

xenonex

2018-12-18 17:23:59

Personal

三倍经验题 ```cpp #include<cstdio> #include<cmath> #define SN 100010 typedef unsigned long long LL; int sqr,prime[SN],pcnt; LL N,k,v[SN],g1[SN],g2[SN],pre[SN],pre2[48]; bool isnp[SN]; void sieve() { for(int i=2;i<=SN;i++) { if(!isnp[i])prime[++pcnt] = i; for(int j=1,k;j<=pcnt&&(k=i*prime[j])<=SN;j++) { isnp[k] = 1; if(i%prime[j] == 0)break; } } } void work_g(LL n) { int i,j,t2; LL end,val,t1; sqr = sqrt(n); for(i=1,j=0;i<=sqr;i++)g1[i] = i-1, g2[i] = (v[++j]=n/i)-1; for(j=1;prime[j]<=sqr;j++) { end = (LL)prime[j]*prime[j]; for(i=1;i<=sqr&&(val=v[i])>=end;i++) t1 = val/prime[j], g2[i] += j-(t1 <= sqr? g1[t1]:g2[n/t1])-1; if((LL)sqr >= end)for(i=sqr,t2=end;i>=t2;i--)g1[i] += j-g1[i/prime[j]]-1; } for(i=1;i<=sqr;i++)g1[i] *= (k+1), g2[i] *= (k+1), pre[i] = -(k+1)*(i-1); for(i=0;i<48;i++)pre2[i] = k*i+1; } LL work_s(LL n,int q) //这个s不是标准写法 { if(prime[q] > n)return 0; if((LL)prime[q]*prime[q] > n)return (n <= sqr? g1[n]:g2[N/n])+pre[q]; LL ans = 0,pc; int e = 1; for(pc=prime[q];pc<=n;pc*=prime[q],e++)ans += (work_s(n/pc,q+1)+1)*pre2[e]; return ans+work_s(n,q+1); } int main() { int T; sieve(), scanf("%d",&T); while(T--)scanf("%llu%llu",&N,&k), work_g(N), printf("%llu\n",work_s(N,1)+1); return 0; } ```