题目描述
小Z想求F(n,k),F(n,k)表示n的所有因数pi中,满足n/pi <= k 的和。
小Z发现还是很水,所以他决定加大难度。
求
小Z还准备了很多个询问。现在你来解决一下吧。
输入输出格式
输入格式:
第一行两个整数m 表示询问的个数
接下来每行两个数ni,ki,表示这个询问的n和k
输出格式:
,
也就是把刚好等于k的答案加进去 然后k变大
对于每个询问输出一行一个整数,表示对应的答案。
题目理解:F(n,k)表示n的所有因数qi中,满足n/qi<=k的和,
m组,每组给定n和k,求 ;
m<=500000,ni<=100000
解析:k比较大的的答案 包含了k比较小的答案,所以要先把每次询问按k来排序,
然后我们每次回答询问的时候 如果k不同 就把k变大成现在要问的k,
也就是把刚好等于k的答案插入线段树, 然后k变大
复杂度 O (nlog^2n+mlogn)代码:
#include<iostream> #include<cstdio> #include<algorithm> #define N 100000 #define ll long long using namespace std; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } ll t[N*3],ans[N*5+10]; int m; struct que{int n,k,id;}e[N*5+10]; bool cmp(que i,que j){return i.k<j.k;} ll query(int l,int r){ ll sum=0; l+=N-1,r+=N-1; sum+=t[l]+t[r]; if(l==r) return sum-=t[l]; for(;l^r^1;l>>=1,r>>=1){ if(~l&1) sum+=t[l^1]; if( r&1) sum+=t[r^1]; } return sum; } void Change(int x,int v){ t[x+=N-1]+=v; while(x) t[x>>=1]=t[x<<1]+t[x<<1|1]; } void sol(int x){ for(int i=1;i*x<=N;i++) Change(i*x,i); } int main(){ m=read(); for(int i=1;i<=m;i++){e[i].n=read();e[i].k=read();e[i].id=i;} sort(e+1,e+m+1,cmp); int j=0; for(int i=1;i<=m;i++){ while(j<e[i].k) sol(++j); ans[e[i].id]=query(1,e[i].n); } for(int i=1;i<=m;i++) printf("%lld\n",ans[i]); return 0; }
时间: 2024-10-05 21:29:09