UVA1655 考试 Exam
Genius_Star · · 题解
思路:
相当于求三元组
考虑枚举
后面那串式子可以数论分块计算,定义:
那么原式可以化为:
发现也可以数论分块,于是数论分块套数论分块就做完了。
时间复杂度约为
但是在本题的极限数据下会超时,考虑进行优化。
注意到:
其中
此时时间复杂度优化到了
完整代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const ll N=2.3e7+7;
inline ll read(){
ll x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')
f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
inline void write(ll x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9)
write(x/10);
putchar(x%10+'0');
}
int T,cnt;
int P[N],F[N];
ll n,A[N];
bitset<N+5> f;
inline ll Fun(ll n){
if(n<N)
return A[n];
ll B=sqrt(n),ans=0;
for(int i=1;i<=B;i++)
ans+=n/i;
return 2ll*ans-B*B;
}
inline void init(){
A[1]=1;
for(int i=2;i<N;i++){
if(!f[i]){
P[++cnt]=i;
A[i]=2;
F[i]=1;
}
for(ll j=1;j<=cnt&&i*P[j]<N;j++){
f[i*P[j]]=1;
if(i%P[j]){
F[i*P[j]]=1;
A[i*P[j]]=A[i]*2ll;
}
else{
F[i*P[j]]=F[i]+1;
A[i*P[j]]=A[i]/(F[i]+1)*(F[i]+2);
break;
}
}
}
for(int i=2;i<N;i++)
A[i]+=A[i-1];
}
inline ll solve(ll n){
ll ans=0,B=sqrt(n),cnt=n/B+B-1;
ll l=0,r=0,lj=0,rj=0;
// cerr<<r<<'\n';
for(ll i=0;i<cnt;i++){
r=i<B?n/(i+1):l-1,rj=Fun(r);
ans+=i?(n/l)*(lj-rj):n;
l=r,lj=rj;
}
return ans;
}
int main(){
// freopen("A.in","r",stdin);
// freopen("A.out","w",stdout);
init();
while(~scanf("%lld",&n))
printf("Case %d: %lld\n",++T,solve(n));
return 0;
}