DIVCNT2 - Counting Divisors (square)
DIVCNT3 - Counting Divisors (cube)
杜教筛
(其实不算是杜教筛,类似杜教筛的复杂度分析而已)
你要大力推式子:
把约数个数代换了
把2^质因子个数 代换了
构造出卷积,然后大于n^(2/3)还要搞出约数个数的式子和无完全平方数的个数的容斥。。。
。。。。
然后恭喜你,spoj上过不去。。。
bzoj能过:
#include<bits/stdc++.h> #define reg register int #define il inline #define ul unsigned long long #define numb (ch^'0') using namespace std; typedef long long ll; il void rd(int &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } namespace Miracle{ const int N=998630; ll n; ul miu[N],sig[N],sq[N]; bool vis[N]; int divcnt[N],pri[N+5],tot; ll a[200005]; ll up; void sieve(ll n){ miu[1]=1;sig[1]=1; for(reg i=2;i<=n;++i){ if(!vis[i]){ pri[++tot]=i; miu[i]=-1; sig[i]=2; divcnt[i]=1; } for(reg j=1;j<=tot;++j){ if(pri[j]*i>n) break; vis[pri[j]*i]=1; if(i%pri[j]==0){ divcnt[i*pri[j]]=divcnt[i]+1; miu[i*pri[j]]=0; sig[i*pri[j]]=sig[i]/(divcnt[i]+1)*(divcnt[i]+2); break; } divcnt[i*pri[j]]=1; miu[i*pri[j]]=-miu[i]; sig[i*pri[j]]=sig[i]*sig[pri[j]]; } } sq[1]=1; for(reg i=2;i<=n;++i) { sq[i]=miu[i]*miu[i]; sq[i]+=sq[i-1]; sig[i]+=sig[i-1]; } } ul M(ll n){ if(n<=up) return sq[n]; ul ret=0; for(reg i=1;(ll)i*i<=n;++i){ ret=ret+miu[i]*(n/(i*i)); } //cout<<" M "<<ret<<endl; return ret; } ul S(ll n){ if(n<=up) return sig[n]; ul ret=0; for(ll i=1,x=0;i<=n;i=x+1){ x=(n/(n/i)); ret=ret+(x-i+1)*(n/i); } // cout<<" S "<<ret<<endl; return ret; } ul solve(ll n){ ul ret=0; for(ll i=1,x=0;i<=n;i=x+1){ x=(n/(n/i)); ret=ret+(M(x)-M(i-1))*S(n/i); // cout<<"["<<i<<","<<x<<"] : "<<ret<<endl; } return ret; } int main(){ int t; rd(t); ll mx=0; for(reg i=1;i<=t;++i) scanf("%lld",&a[i]),mx=max(mx,a[i]); if(mx<=N-5){ up=mx; sieve(up); }else{ up=N-5; sieve(up); } for(reg i=1;i<=t;++i){ printf("%llu\n",solve(a[i])); } return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2019/3/6 21:18:05 */