【0521模擬賽】小Z愛數學
阿新 • • 發佈:2017-05-28
csu 復雜度 ace pan chan printf 排序 fine 個數
復雜度 O (nlog^2n+mlogn) 代碼:
題目描述
小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,intr){ 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; }
【0521模擬賽】小Z愛數學