1 条题解
-
3
对于 ,。易发现 不下降,且 。
由于 且 为奇数时 为偶数, 为偶数时 ,所以有另一个结论是使 的正整数 的最小值不大于 。
因此考虑找出最小的 使 。这样对于 ,$f(x)=x \Longrightarrow \sum_{i=1}^{x}f(i)=\frac{x(x+1)}{2}$。再考虑找出最大的 使 ,这样对于 ,有 。
设 ,显然 的数值不会太大。因此考虑预处理出 和 和 ,那么就可以在 的时间内求出任意 。因此把询问拆成 后询问复杂度为 。
然后再考虑预处理部分的复杂度,因为 ,考虑将 初值设为 ,在 满足 前不断进行 的操作。这里又发现如果存在一个素数 满足 ,。因此 增加的次数不会超过 以内的最大素数距离。类似地, 的数值不会超过 以内的最大素数距离 。打表得 。由于求 的复杂度为 ,函数嵌套的次数不大于 ,因此预处理的总复杂度为 。
总复杂度为 ,远远跑不满,可以通过本题。
贴一个代码
#include<bits/stdc++.h> #define uint unsigned int #define ll long long #define ull unsigned long long #define PII pair<int,int> #define PLL pair<ll,ll> #define DU double #define rep(i,x,n) for(int i=(x);i<=(n);i++) #define nep(i,x,n) for(int i=(x);i>=(n);i--) using namespace std; const int N=1e5+10; int T,B,lim,st[N],pr[N],phi[N],cntp; ll s[N],tot; unordered_map<int,int>p; inline int read(){ int s=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); } return s*f; } inline void print(ll x){ if(x<0){ putchar('-'); x=-x; } if(x>9) print(x/10); putchar(x%10+'0'); } inline void initp(){ st[1]=1,phi[1]=1; rep(i,2,1e5){ if(!st[i]) pr[++cntp]=i,phi[i]=i-1; for(int j=1;i*pr[j]<=1e5;j++){ st[i*pr[j]]=1; if(i%pr[j]==0){phi[i*pr[j]]=phi[i]*pr[j];break;} phi[i*pr[j]]=phi[i]*(pr[j]-1); } } } inline int Phi(int x){ if(x<=1e5) return phi[x]; if(p[x]) return p[x]; int res=x; rep(i,1,cntp){ if(pr[i]>x/pr[i]) break; if(x%pr[i]==0){ res=res/pr[i]*(pr[i]-1); while(x%pr[i]==0) x/=pr[i]; } } if(x>1) res=res/x*(x-1); return p[x]=res; } inline int getp(int u,int x){ if(u<=0) return x; if(x==1) return x; return getp(u-1,Phi(x)); } inline void init(){ int now=B; while(Phi(now)<=B&&now<=1e9) now++; lim=now-1; } inline void initb(){ for(int i=lim+1,now=Phi(lim);i<=1e9;i++){ now=max(now,Phi(i)); if(now>=B+60) break; s[i-lim]=s[i-lim-1]+getp(now-B,i),tot++; } } inline ll getans(int x){ if(x==0) return 0; if(x<=lim) return (ll)x*(x+1)/2; if(x>lim+tot) return (ll)lim*(lim+1)/2+(x-(lim+tot))+s[tot]; return (ll)lim*(lim+1)/2+s[x-lim]; } inline void Solve(){ T=read(),B=read();initp();init();initb(); rep(i,1,T){ int x=read(),y=read(); print(getans(y)-getans(x-1)),puts(""); } } int main(){ int Tests=1; while(Tests--) Solve(); return 0; }
信息
- ID
- 158
- 时间
- 1000ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- (无)
- 递交数
- 104
- 已通过
- 4
- 上传者